1 / 23

Programozás III.

Programozás III. Automatikus állapotértesítés adatkötéskor (…Changed, INofityPropertyChanged, ObservableCollection<T>) Adatformázások Adatkonverziók Erőforrások. Példa. Cél: a személy neve legyen kiírva (adatkötés DataContext állítással), a gombbal lehessen változtatni

varsha
Download Presentation

Programozás III.

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programozás III. Automatikus állapotértesítés adatkötéskor (…Changed, INofityPropertyChanged, ObservableCollection<T>) Adatformázások Adatkonverziók Erőforrások

  2. Példa • Cél: a személy neve legyen kiírva (adatkötés DataContext állítással), a gombbal lehessen változtatni • Adatkötés a XAML-ben: publicMainWindow() { InitializeComponent(); aktualisSzemely= newSzemely("Piros Péter"); this.DataContext= aktualisSzemely; } <Label Content="{Binding Nev}"/>

  3. Példa folytatás • A gomb Click eseménykezelője: • A konzol kiírás szerint megtörtént a változtatás… • … az adatkötésben semmi sem látszik! privatevoidButton_Click(objectsender, RoutedEventArgse) { aktualisSzemely.Nev= "Kék Péter"; Console.WriteLine(aktualisSzemely.Nev); }

  4. Automatikus állapotértesítés adatkötéskor • Ahhoz, hogy az adatkötések működjenek, a kötés céljának értesítést kell kapnia a forrás adott tulajdonságának a megváltozásáról • Eddigi kötéseinkben többnyire keretrendszeri osztályok tulajdonságai voltak a források… • Pl. a Slider Value tulajdonsága volt a forrás, és a Label Content-je a cél • Ezekben meg van oldva, hogy az adatkötés célját értesíteni tudják • … vagy pedig saját objektum volt a forrás, de csak az adatkötésen keresztül változtatuk benne az adatot • Pl. a lejátszási listás példaprogramban a Szám típusú objektumok Megjegyzés tulajdonsága volt a forrás, ezt változtatgattuk az adatkötésen keresztül • Saját objektumaink alapesetben nem küldenek értesítést a változásukról!

  5. Automatikus állapotértesítés adatkötéskor • Módszerek: • A függőségi tulajdonságok képesek arra, hogy megváltozásukról automatikus értesítést küldjenek. Megoldás: a forrástulajdonság ne sima, hanem függőségi tulajdonság legyen! (nem tárgyaljuk) • …Changed esemény kiváltása a tulajdonság változásakor • INotifyPropertyChanged interfész implementálása

  6. Állapotértesítés – …Changed esemény • A tulajdonság értékének változásakor tüzeljen egy …Changed esemény (…=tulajdonság neve) • Az eseményre való feliratkozás az adatkötéskor automatikus publiceventEventHandlerNevChanged; publicstringNev { get{ returnnev; } set { nev= value; EventHandlernevChanged= NevChanged; if (nevChanged!= null) nevChanged(this, EventArgs.Empty); } }

  7. Állapotértesítés – INotifyPropertyChanged • A tulajdonságot deklaráló osztály implementálja az INotifyPropertyChanged interfészt (System.ComponentModel) • Ebben egyetlen esemény van • public event PropertyChangedEventHandler PropertyChanged; • Ez tüzeljen a tulajdonság értékének változtatásakor, az EventArgs paramétere a tulajdonság neve legyen • string.Empty vagy null, ha az összes tulajdonság megváltozott publicstringNev { get{ returnnev; } set { nev= value; PropertyChangedEventHandlerhandler = PropertyChanged; if (handler != null) handler(this, newPropertyChangedEventArgs("Nev")); } }

  8. Állapotértesítés – INotifyPropertyChanged • Előny az előzőhöz képest: nem kell annyi esemény • Gyakran egynél több tulajdonságnál akarják használni: OnPropertyChanged() privatevoidOnPropertyChanged(stringpropertyName) { PropertyChangedEventHandlerhandler = PropertyChanged; if (handler!= null) handler(this, newPropertyChangedEventArgs(propertyName)); } publicstringNev { get{ returnnev; } set { nev= value; OnPropertyChanged("Nev"); } }

  9. Állapotértesítés – Problémák gyűjteményekkel • Gyűjtemény típusú forrástulajdonságnál az adatkötött GUI-elem (pl. ListBox) a forrásgyűjtemény lecserélését detektálja csak, ha az OnPropertyChanged()-et a setterben hívjuk • Ez nem detektálja: • Ha a gyűjtemény valamelyik elemét lecseréljük • Add()/Remove()/Insert()… • Ha a gyűjtemény valamelyik elemének egy tulajdonságát módosítjuk publicList<HirlevelFeliratkozas> HirlevelFeliratkozasok { get{ returnhirlevelFeliratkozasok; } set { hirlevelFeliratkozasok= value; OnPropertyChanged("HirlevelFeliratkozasok"); //??? } }

  10. Állapotértesítés – Problémák gyűjteményekkel List<HirlevelFeliratkozas> uj = newList<HirlevelFeliratkozas>(); uj.Add(newHirlevelFeliratkozas("gyereknevelés", true)); aktualisSzemely.HirlevelFeliratkozasok= uj; //frissít aktualisSzemely.HirlevelFeliratkozasok[0] = newHirlevelFeliratkozas("gyereknevelés", true); //nem frissít aktualisSzemely.HirlevelFeliratkozasok.Add( newHirlevelFeliratkozas("gyereknevelés", true)); //nem frissít aktualisSzemely.HirlevelFeliratkozasok[0].Aktiv = false; //nem frissít

  11. Állapotértesítés – ObservableCollection<T> • List<T>-hez hasonlóan kell használni • System.Collections.ObjectModel • Értesítést küld: • Ha a gyűjtemény valamelyik elemét lecseréljük • Add()/Remove()/Insert() • Elem tulajdonságának módosításakor NEM! • INotifyCollectionChanged interfészt implementál • Saját osztályaink számára is implementálható, de akkor a fenti esetekre mind gondolni kell privateObservableCollection<HirlevelFeliratkozas> hirlevelFeliratkozasok; publicObservableCollection<HirlevelFeliratkozas> HirlevelFeliratkozasok { get{ returnhirlevelFeliratkozasok; } set { hirlevelFeliratkozasok= value; OnPropertyChanged("HirlevelFeliratkozasok"); } }

  12. Állapotértesítés – ObservableCollection<T> ObservableCollection<HirlevelFeliratkozas> uj = newObservableCollection<HirlevelFeliratkozas>(); uj.Add(newHirlevelFeliratkozas("gyereknevelés", true)); aktualisSzemely.HirlevelFeliratkozasok= uj; //frissít aktualisSzemely.HirlevelFeliratkozasok[0] = newHirlevelFeliratkozas("gyereknevelés", true); //frissít aktualisSzemely.HirlevelFeliratkozasok.Add( newHirlevelFeliratkozas("gyereknevelés", true)); //frissít aktualisSzemely.HirlevelFeliratkozasok[0].Aktiv = false; //nem frissít!

  13. Állapotértesítés – Fennmaradó problémák • ToString()-es kiírásaink sohasem frissülnek… • Lehetőleg elkerüljük a használatát! • Helyette: • Törekszünk egyenként kiírni a tulajdonságokat, adatkötésekkel • ListBoxban ehhez ún. DataTemplate kell, vagy ha egy tulajdonság kiírása elég, akkor DisplayMemberPath • Vannak más megoldások is (nem tárgyaljuk őket)

  14. DataTemplate classSzemely : INotifyPropertyChanged { … privateObservableCollection<HirlevelFeliratkozas> hirlevelFeliratkozasok; publicObservableCollection<HirlevelFeliratkozas> HirlevelFeliratkozasok { get{ returnhirlevelFeliratkozasok; } set { hirlevelFeliratkozasok= value; OnPropertyChanged("HirlevelFeliratkozasok"); } } //+HirlevelFeliratkozas osztályban is implementálvafy- } //van az INotifyPropertyChanged <ListBox ItemsSource="{Binding HirlevelFeliratkozasok}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Label Content="{Binding Tema}"/> <Label Content="{Binding Aktiv}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> Az ItemsControloknak az ItemTemplate, a ContentControloknak a ContentTemplate tulajdonságába mehet ilyen DataTemplate, Panel utódoknál CellTemplate

  15. Állapotértesítés – konklúzió... • Minden korrekt megoldáshoz kell: • INotifyPropertyChanged implementálása az adatkötésben felhasznált összes osztályban • ObservableCollection<T> a többi gyűjtemény helyett • ToString() kerülése • Ha komplex szöveg kéne: a ma még tárgyalt StringFormat és Converter segíthet ebben... (+más megoldások)

  16. Adatformázások, adatkonverziók • Gyakran nem szerencsés, ha az adatkötés forrástulajdonságának értéke változatlanul jelenik meg • Formázások: • Legkönnyebben: …StringFormat tulajdonságok • ContentControl-oknál: ContentStringFormat tulajdonság (nem csak adatkötésnél használható!) • ItemsControl-oknál: ItemStringFormat tulajdonság (nem csak adatkötésnél használható!) • Adatkötéseknél, CSAK HA string a céltulajdonság (pl. TextBox.Text), akkor a {Binding}-on belül StringFormat • Hasonlóan kell használni, mint a string.Format formázóstringjeit (speciális szabályok lehetnek) <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Label ContentStringFormat="Hírlevéltéma: {0}" Content="{Binding Tema}"/> <Label ContentStringFormat="Feliratkozás aktív: {0}" Content="{Binding Aktiv}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate>

  17. Adatformázások, adatkonverziók • Adatkonverziók: • Gyakran automatikus! • Pl: ListBox kerete vegye fel a ListBox-ban kijelölt színt. A ListBox-ban lévő elemek stringek. • Egyébként az IValueConverter interfészt implementáló konverterosztállyal valósítható meg (System.Windows.Data) • Két metódusa: Convert(), ConvertBack() • Convert(): amikor az értéket átadjuk a forrásból a célba • ConvertBack(): amikor a forrás megkapja az értéket a célból (kétirányú vagy forrás felé irányuló kötésmód esetén) • A ConvertBack() után, amikor a forrásba került az érték, még egyszer hívódik a Convert(). <ListBox x:Name="listBoxSzinek" BorderBrush= "{Binding ElementName=listBoxSzinek,Path=SelectedItem}” .../>

  18. Adatformázások, adatkonverziók • Személy osztály: • Név (string) • Kor (int) • Kötés: szemely.Kor  label.Content <Window... xmlns:current="clr-namespace:WpfApplication9” ...> <Grid> <Grid.Resources> <current:KorValueConverter x:Key="KorConverter"/> </Grid.Resources> <Label Content="Személy neve:".../> <Label Content="Személy kora kb.:".../> <Label Content="{Binding Nev}” .../> <Label Content="{Binding Kor, Converter={StaticResource KorConverter}}” ... /> </Grid> </Window> Névtér behivatkozása KorConverter néven hivatkozható konvertáló példány létrehozása a Grid erőforrásszótárában Konvertáló hozzárendelése a kötéshez

  19. Adatformázások, adatkonverziók • Konvertáló osztály • Csak egyirányú kötésre alkalmas ebben a formában, egyébként a visszafelé való konverzió implementálása is szükséges lenne classKorValueConverter : IValueConverter { publicobjectConvert(objectvalue, TypetargetType, objectparameter, System.Globalization.CultureInfoculture) { intkor = (int)value; if (kor < 18) return"gyerek"; elseif (kor < 30) return"fiatal"; elseif (kor < 50) return"középkorú"; elseif (kor < 65) return"idősebb"; else return"idős"; } publicobjectConvertBack(objectvalue, TypetargetType, objectparameter, System.Globalization.CultureInfoculture) { thrownewNotImplementedException(); } }

  20. Erőforrások • Az erőforrás olyan objektum, amit különféle helyeken fel/újrahasználhatunk az alkalmazásunkban • Típusok: • Logikai/objektum erőforrások: tetszőlegesen (XAML-ben) létrehozott objektumok • Bináris erőforrások: képek, ikonok, sztringtáblázatok stb. • A logikai erőforrásokat az erőforrásszótár tartalmazza, mindegyik el van látva névvel (x:Key) • Resources tulajdonság (FrameworkElement utódokban) • Tartalmazott elemek megkapják a tartalmazójuk erőforrásait <Window... <Grid> <Grid.Resources> <current:KorValueConverter x:Key="KorConverter"/> </Grid.Resources> ... </Grid> </Window> KorConverter néven hivatkozható objektumerőforrás (KorValueConverter példány) létrehozása a Grid erőforrásszótárában

  21. Erőforrások • Logikai/objektumerőforrások használata még rengeteg más helyen: • Ecsetek, színek, stílusok, Data Template-ek, konverterek, tetszőleges objektumok (pl. tömbök)… • Pl: szín (ecset) létrehozása az erőforrásszótárban: • Fajtái: • StaticResource: a XAML betöltésekor, egyszer töltődik be, ezután a változtatásokat nem veszi figyelembe • DynamicResource: futásidőben töltődik be, változtatható <Window...> <Grid> <Grid.Resources> <SolidColorBrush x:Key="kedvencSzinem" Color="Azure"/> </Grid.Resources> ... <Label Background="{StaticResource ResourceKey=kedvencSzinem}" Content="Szép színű" .../> <ListBox Background="{StaticResource ResourceKey=kedvencSzinem}" .../> </Grid> </Window>

  22. Erőforrások • Bináris erőforrások: • A projekthez bármilyen fájl hozzáadható, amire az alkalmazásnak később szüksége lehet • A bináris erőforrások közé való felvételük a megfelelő fordítási beállítással érhető el (Solution Explorerben kijelölés, Properties ablak – Build Action) • Resource: a fordító a .NET szerelvénybe építi az adatokat – előnye, hogy így mindig az alkalmazás rendelkezésére állnak • Content: az adatok külön fájlokként állnak rendelkezésre – lecserélhetők, de figyelmetlen felhasználó pl. törölheti őket • Fájlnév szerint hivatkozunk rájuk a XAML-ben <Image Source="LockScreen___0600_0337.jpg" />

  23. Feladat

More Related