NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
Avatar
Jakub Hrdoun
Člen
Avatar
Jakub Hrdoun:2.9.2017 21:42

Ahoj,
poprvé používám rozhraní INotifyProper­tyChanged. Přečetl jsem si tutoriál tady i pár věcí na stackoverflow, ale stále se mi nedaří.
Co potřebuji: Když se mi změní objekt krtek, potřebuji nastavit ulozeno na false. Zkoušel jsem tohle:

public class Wrapper : INotifyPropertyChanged
    {

public event PropertyChangedEventHandler PropertyChanged;

        public Krtek krtek { get; set; }

        public bool ulozeno { get; set; }

        public Wrapper()
        {
            PropertyChanged += Wrapper_PropertyChanged;
        }

        private void Wrapper_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "krtek")
            {
                ulozeno = false;
            }
        }
    }
 
Odpovědět
2.9.2017 21:42
Avatar
zelvicek
Člen
Avatar
Odpovídá na Jakub Hrdoun
zelvicek:2.9.2017 22:07

Při čtení těch tutorial jsi něco přeskočil. Třeba tady (https://docs.microsoft.com/…ed-interface) je to jasně vidět.
A jako nápověda: kdo by měl tu událost vyvolávat?

 
Nahoru Odpovědět
2.9.2017 22:07
Avatar
Jakub Hrdoun
Člen
Avatar
Odpovídá na zelvicek
Jakub Hrdoun:2.9.2017 23:02

Díky za odpověď. Ale ptám se tady já :-) .
S tím si právě moc nevím rady. Ten Microsoftí kód jsem prohlížel, ale hlava mi to nebere; mám-li volat ze setteru něco jako tohle

private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

jak se tam píše, k čemu pak to rozhraní je, když si z toho setteru můžu klidně zavolat metodu, která mi provede, co potřebuji?

 
Nahoru Odpovědět
2.9.2017 23:02
Avatar
Neaktivní uživatel:2.9.2017 23:30

Ty mas v settru, nebo kde koliv to potrebujes, volat NotifyPropertyChan­ged s prislusnym nazvem Property, ktera je bindovana do DataContextu UI.

Nahoru Odpovědět
2.9.2017 23:30
Neaktivní uživatelský účet
Avatar
krepsy3
Tvůrce
Avatar
krepsy3:3.9.2017 8:51

Do třídy si připrav nějakou obslužnou metodu, kterou budeš volat ze setterů, aby Invokovala event typu PropertyChynge­dEventHandler.

public class Wrapper : INotifyPropertyChanged
{
        public event PropertyChangedEventHandler PropertyChanged;
        private void UpdatePoperty(string propertyName)
        {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private Krtek _krtek;
        public Krtek krtek { get { return _krtek; } set { _krtek = value; UpdateProperty("Krtek"); } }

        public bool ulozeno { get; set; }

        public Wrapper()
        {
                PropertyChanged += Wrapper_PropertyChanged;
        }

        private void Wrapper_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
                if (e.PropertyName == "krtek")
                {
                        ulozeno = false;
                }
        }
}
Editováno 3.9.2017 8:52
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
3.9.2017 8:51
Programátor je stroj k převodu kávy na kód.
Avatar
zelvicek
Člen
Avatar
Odpovídá na Jakub Hrdoun
zelvicek:3.9.2017 9:34

Předně:
nesouhlasím s výrokem "Ale ptám se tady já :-)" - žádný dotaz jsi nepoložil. A i kdyby jsi jej položil, neubírá to právo pokládat dotazy mi.

Ale k věci: nejsem si jistý, že se chápem, takže se trošku rozepíšu.

  1. Jakýkoliv interface je proto, aby se dalo přistupovat k memberům objektu, který ten interface implementuje. Příklad: libovolná methoda xyz, jež má proměnnou typu INotifyProper­tyChanged, může objektu (implementaci toho INotifyProper­tyChanged) nastavit na PropertyChanged nějaký handler. Tím má ta methoda xyz zajištěn "odposlech" změn vlastností.
  2. Pokud jen potřebuješ ve svém objektu sledovat stav uložení, ten interface vůbec nepotřebuješ.
class Dolovac
{
        private Krtek _krtek;
        public Krtek Krtek { get {return _krtek;} set; {_krtek=value; _isDirty=true;} }

        private bool _isDirty;
        public bool IsDirty() {return _isDirty;}
}

A abych ti trošku zvedl adrenalín: který případ potřebuješ ty?

 
Nahoru Odpovědět
3.9.2017 9:34
Avatar
Petr Čech
Tvůrce
Avatar
Petr Čech:3.9.2017 12:08

Jádrem tohoto problému je ze INotifyProper­tyChanged se neimplementuje automaticky, ty tu událost stejně musíš při každé změně vlastnosti volat manuálně. To rozhraní je tu proto, aby se s takovými objekty zacházelo standardní cestou.
Pokud chceš jen kontrolovat, jestli se změnil stav, údělej si metodu invalidate(), která bude ukládat do vlastnosti IsChanged s privátním setterem true v setteru každé jiné vlastnosti. Pseudo kód z mobilu:

void Invalidate() { IsChanged = true;}
public bool IsChanged {get; private set}
private internet _otherProp;
public int OtherProp {get {return _otherProp;} set {invalidate ();_other property = value ;}}
Nahoru Odpovědět
3.9.2017 12:08
the cake is a lie
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Petr Čech
Petr Čech:3.9.2017 12:12

Samozřejmě int a ne internet :D

Nahoru Odpovědět
3.9.2017 12:12
the cake is a lie
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na zelvicek
Petr Čech:3.9.2017 12:14

Neodpustím si rýpnutí, ale myslím že nevíš, jak funguje adrenalin ;-)

Nahoru Odpovědět
3.9.2017 12:14
the cake is a lie
Avatar
Jakub Hrdoun
Člen
Avatar
Jakub Hrdoun:3.9.2017 16:08

Díky moc všem za odpovědi.
Řešení bez toho interfacu co navrhl Petr Čech a zelvicek byla věc, která mě napadla vůbec na začátku, jenže nefungovala. V čem je problém; objekt Krtek je plný listů obsahující dalších objekty - takže je veliký. Když se během běhu aplikace tenhle rozsáhlý objekt změní, neměním ho celý, ale jenom přidám/odeberu něco z těch listů a - PROBLÉM - nezavolá se setter. Což je docela smutné.
Minimálně pro mě je to velmi zajímavé zjištění, že změním-li vlastnost v objektu (já to měním zevnitř, tedy zavolám metodu něco jako Zmen(), která v objektu Krtek přidá/odebere/u­praví objekty v listech, ale zvenku by to bylo stejné), tak se nezavolá její setter. Možná to víte, ale já to nevěděl :-) . (Stackoverflow dí: https://stackoverflow.com/…-is-modified )

No a proč jsem se tedy ptal na INotifyProper­tyChanged? Páč jsem myslel, že je to tak chytrý, že to tenhle problém nějak obejde. Vzhledem k tomu, že je třeba volat ten event ze setteru, tak to asi fungovat nebude.

 
Nahoru Odpovědět
3.9.2017 16:08
Avatar
Odpovídá na Jakub Hrdoun
Patrik Valkovič:3.9.2017 16:15

Nefunguje to protože si pleteš základní principy. INotifyProper­tyChanged nemá s vnitřní implementací nic společného, ten slouží k informování okolí, že se něco změnilo. Setter se nevolá, protože ten atribut nenastavuješ.

Nahoru Odpovědět
3.9.2017 16:15
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
zelvicek
Člen
Avatar
Odpovídá na Jakub Hrdoun
zelvicek:3.9.2017 16:35

Setter property krtek se nevolá - logicky - hodnota vlastnoti se nemění (ten důvod zazněl I v tom stackoverflow).
Pokud by třída Krtek byla implementací INotifyProper­tyChanged, mohla by třída Wrapper "odposlouchávat" změny na objektu uloženém ve vlastnosti krtek. Ale neraduj se, naimplementovat ten interface (dle tvého popisu) nebude jednoduché - musel by sis udělat vlastní implementace těch listů.
Je asi na zvážení změna konceptu tvé aplikace.

 
Nahoru Odpovědět
3.9.2017 16:35
Avatar
krepsy3
Tvůrce
Avatar
krepsy3:3.9.2017 23:02

Pokud potřebuješ reagovat na změny v kolekcích, musíš použít ObservableCollec­tion, protože změnou hodnoty nějaké položky v Listu se samotná instance typu List nijak nezmění, to je v případě přidávání/odebírání položek :)

Nahoru Odpovědět
3.9.2017 23:02
Programátor je stroj k převodu kávy na kód.
Avatar
Jakub Hrdoun
Člen
Avatar
Odpovídá na krepsy3
Jakub Hrdoun:4.9.2017 16:35

O ObservableCollec­tion jsem přemýšlel, nakonec jsem se rozhodl pro jednodušší řešení; mám tam pomocné metody, které v tom objektu Krtek dělají pořádek, a do nich jsem přidal volání příslušné metody,která nastaví ulozeno na false.

Každopádně díky všem, že jste si udělali chvíli čas na můj dotaz.

 
Nahoru Odpovědět
4.9.2017 16:35
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 14 zpráv z 14.