Diskuze: INotifyPropertyChanged
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 14 zpráv z 14.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
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?
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?
Ty mas v settru, nebo kde koliv to potrebujes, volat NotifyPropertyChanged s prislusnym nazvem Property, ktera je bindovana do DataContextu UI.
Do třídy si připrav nějakou obslužnou metodu, kterou budeš volat ze setterů, aby Invokovala event typu PropertyChyngedEventHandler.
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;
}
}
}
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.
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?
Jádrem tohoto problému je ze INotifyPropertyChanged 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 ;}}
Neodpustím si rýpnutí, ale myslím že nevíš, jak funguje adrenalin
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/upraví 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 INotifyPropertyChanged? 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.
Nefunguje to protože si pleteš základní principy. INotifyPropertyChanged 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š.
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í INotifyPropertyChanged, 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.
Pokud potřebuješ reagovat na změny v kolekcích, musíš použít ObservableCollection, 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
O ObservableCollection 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.
Zobrazeno 14 zpráv z 14.