Benutzer mit den meisten Antworten
Grundlegen: Objekte darstellen und bearbeiten können.

Frage
-
Hallo!
Ich möchte ein Liste von Personen in einem Grid darstellen und diese anschließend löschen und hinzufügen können.
Und dafür suche ich den Best Practice Weg bzw. stoße bei meinem Versuchen auf Probleme!
Folgendes habe ich probiert:public partial class MainPage : UserControl { List<Person> personen = new List<Person>(); public MainPage() { InitializeComponent(); } public void AnzeigeAktualisieren() { this.xamGrid1.ItemsSource = null; this.xamGrid1.ItemsSource = personen; } private void UserControl_Loaded(object sender, RoutedEventArgs e) { personen.Add(new Person() { Alter = 35, Nachname = "Mustermann", Vorname = "Max" }); //personen.Add(new Person() { Alter = 30, Nachname = "Mair", Vorname = "Josef" }); //personen.Add(new Person() { Alter = 20, Nachname = "Smith", Vorname = "John" }); AnzeigeAktualisieren(); } private void buttonHinzufügen_Click(object sender, RoutedEventArgs e) { personen.Add(new Person() { Vorname = this.textBox1.Text, Nachname = this.textBox2.Text, Alter = 1 }); AnzeigeAktualisieren(); } private void buttonEntfernen_Click(object sender, RoutedEventArgs e) { personen.Remove((Person)this.xamGrid1.ActiveCell.Row.Data); AnzeigeAktualisieren(); } }
public class Person { public string Vorname { get; set; } public string Nachname { get; set; } public int Alter { get; set; } }
Das ganze klappt schon mal.
1. Frage: Aber ist das ganze bis hierher überhaupt richtig?
Wie stelle ich das gleiche mit komplexeren Objekten an wie z.b.:public class Person { public string Vorname { get; set; } public string Nachname { get; set; } public int Alter { get; set; } public Person Vorgesetzter { get; set; } }
Meine Überlegung hierfür wäre, dass ich linq verwende:public partial class MainPage : UserControl { List<Person> personen = new List<Person>(); public MainPage() { InitializeComponent(); } public void AnzeigeAktualisieren() { this.xamGrid1.ItemsSource = from p in personen select new { p.Vorname, p.Nachname, p.Alter, Vorgesetzter = p.Vorgesetzter.Nachname, objekt = p }; } private void UserControl_Loaded(object sender, RoutedEventArgs e) { Person pChef = new Person() { Alter = 40, Vorname="Will", Nachname = "Smith"}; Person pMitarbeiter = new Person() {Alter = 35, Nachname = "Mustermann", Vorname = "Max", Vorgesetzter = pChef}; personen.Add(pMitarbeiter); //personen.Add(new Person() { Alter = 30, Nachname = "Mair", Vorname = "Josef" }); //personen.Add(new Person() { Alter = 20, Nachname = "Smith", Vorname = "John" }); AnzeigeAktualisieren(); } private void buttonHinzufügen_Click(object sender, RoutedEventArgs e) { personen.Add(new Person() { Vorname = this.textBox1.Text, Nachname = this.textBox2.Text, Alter = 1 }); AnzeigeAktualisieren(); } private void buttonEntfernen_Click(object sender, RoutedEventArgs e) { personen.Remove((Person)this.xamGrid1.ActiveCell.Row.Cells["objekt"].Value); AnzeigeAktualisieren(); } }
lg Gilbert- Bearbeitet myGil Dienstag, 25. Oktober 2011 09:17
Dienstag, 25. Oktober 2011 09:15
Antworten
-
Hi Gilbert,
ich vermute, Du verwendest NetAdvantage von Infragistic, die ich nicht kenne und für die ich Dir keine darauf spezialisierte Antwort geben kann. Auch ist nicht ersichtlich, wie die Spalten des Grids an die jeweiligen Eigenschaften der "Person" kommen. Ich beschreibe Dir also das Vorgehen für ein im Standard (4.0) enthaltenes DataGrid - und gehe davon aus, dass Infragistics Silverlight-Controls dieses grundsätzliche Verhalten auch beherrschen.
Für die meiner Meinung nach korrekte Abhandlung der Liste einfacher Personen benötigst Du:
1. eine Klasse, in der Du die darzustellenden Daten ablegst. Diese nennen wir "ViewModel" und sie bekommt zwei Eigenschaften: eine Liste der Personen und eine aktuelle Person, z. B.:
public class ViewModel { public ObservableCollection<Person> Persons { get; private set; } public Person CurrentPerson { get; set; } }
2. Deine UserControl-Klasse; sie bekommt im constructor die zusätzliche Zeile:
this.DataContext = new ViewModel();
Der gesamte übrige Code-Behind fliegt raus.
3. Den XAML-Code des UserControls mit (anstatt des xamGrid1):<sdk:DataGrid ItemsSource="{Binding Path=Persons}" SelectedItem="{Binding Path=CurrentPerson}" AutoGenerateColumns="True" />
Den namespace "sdk" definierst Du als:xmlns:sdk=http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk
Jetzt hast Du ein (fertiges) Programm, das in einem DataGrid eine editierbare Liste von Personen anzeigt. Die Spalten werden automatisch aus den Eigenschaften der Klasse Person gebildet (ich nehme an, das ist bei Infragistic genauso ... und kann genauso 'überstimmt' werden).
Zur Erklärung:
Der "DataContext" dient als Datenquelle hinter dem UI. Indem Du das ViewModel dort einstellst, bietest Du dem UI die Möglichkeit per "Binding" auf dessen Eigenschaften zuzugreifen (dies ist ein TOP-Feature der WPF und afaic Grund genug, sie benutzen).
Damit das UI von Änderungen in den gebundenen Eigenschaften etwas mitbekommt, müssen diese bestimmte kommunikative Voraussetzungen erfüllen. Darum habe ich eine "ObservableCollection" anstatt Deiner "List" für die "Persons" verwendet; die sagt nämlich Bescheid, wenn ihren Elementen etwas zugefügt/weggenommen wird. Wenn Du jetzt programmatisch Datensätze einfügen / löschen willst, brauchst Du nur die entsprechende Aktion mit der OC durchzuführen und die (fürchterliche) "AnzeigeAktualisieren"-Funktion kann entfallen.
Das Zufügen eines Datensatzes zu der OC gehört jetzt natürlich in die Klasse ViewModel, in der Du noch einen 'Ersatz' für das Button-Click-Ereignis brauchst. Dazu bindest Du die "Command"-Eigenschaft des Buttons z. B. an die ViewModel-Eigenschaft:
ICommand AddCommand { private set; get; }
In dessen Execute-Methode kannst Du einfügen (oder löschen in einem DeleteCommand). Den zu löschenden Eintrag (den aktuellen Datensatz) findest Du übrigens ohne weiteres Zutun in "CurrentPerson".Die wenigen noch fehlenden Dinge findest z. B. beim "RelayCommand" von Laurent Bugnions "MVVM light". Außerdem schaue Dir das interface INotifyPropertyChanged an; dieses wird benötigt, wenn eine programmatische Änderung z. B. an einem Vornamen dem UI mitgeteilt werden soll.
Bei der komplexeren Personenliste ist wohl das größte Problem: wie stelle ich den "Chef" dar bzw. wie lasse ich ihn bearbeiten. Wenn die Bearbeitung bloß im Auswählen aus einer Liste Chefs besteht, kann recht einfach eine ComboBox dafür verwendet werden (das DataGrid stellt dafür eine "DataGridTemplateColumn" bereit). Für umfangreichere Editieraktionen ist sicher ein eigenes UI gerechtfertigt.
Gruß
Jürgen- Bearbeitet Jürgen Röhr Dienstag, 25. Oktober 2011 19:36 falsche namespace Darstellung
- Als Antwort markiert Robert Breitenhofer Dienstag, 8. November 2011 12:19
Dienstag, 25. Oktober 2011 19:32
Alle Antworten
-
Hi Gilbert,
ich vermute, Du verwendest NetAdvantage von Infragistic, die ich nicht kenne und für die ich Dir keine darauf spezialisierte Antwort geben kann. Auch ist nicht ersichtlich, wie die Spalten des Grids an die jeweiligen Eigenschaften der "Person" kommen. Ich beschreibe Dir also das Vorgehen für ein im Standard (4.0) enthaltenes DataGrid - und gehe davon aus, dass Infragistics Silverlight-Controls dieses grundsätzliche Verhalten auch beherrschen.
Für die meiner Meinung nach korrekte Abhandlung der Liste einfacher Personen benötigst Du:
1. eine Klasse, in der Du die darzustellenden Daten ablegst. Diese nennen wir "ViewModel" und sie bekommt zwei Eigenschaften: eine Liste der Personen und eine aktuelle Person, z. B.:
public class ViewModel { public ObservableCollection<Person> Persons { get; private set; } public Person CurrentPerson { get; set; } }
2. Deine UserControl-Klasse; sie bekommt im constructor die zusätzliche Zeile:
this.DataContext = new ViewModel();
Der gesamte übrige Code-Behind fliegt raus.
3. Den XAML-Code des UserControls mit (anstatt des xamGrid1):<sdk:DataGrid ItemsSource="{Binding Path=Persons}" SelectedItem="{Binding Path=CurrentPerson}" AutoGenerateColumns="True" />
Den namespace "sdk" definierst Du als:xmlns:sdk=http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk
Jetzt hast Du ein (fertiges) Programm, das in einem DataGrid eine editierbare Liste von Personen anzeigt. Die Spalten werden automatisch aus den Eigenschaften der Klasse Person gebildet (ich nehme an, das ist bei Infragistic genauso ... und kann genauso 'überstimmt' werden).
Zur Erklärung:
Der "DataContext" dient als Datenquelle hinter dem UI. Indem Du das ViewModel dort einstellst, bietest Du dem UI die Möglichkeit per "Binding" auf dessen Eigenschaften zuzugreifen (dies ist ein TOP-Feature der WPF und afaic Grund genug, sie benutzen).
Damit das UI von Änderungen in den gebundenen Eigenschaften etwas mitbekommt, müssen diese bestimmte kommunikative Voraussetzungen erfüllen. Darum habe ich eine "ObservableCollection" anstatt Deiner "List" für die "Persons" verwendet; die sagt nämlich Bescheid, wenn ihren Elementen etwas zugefügt/weggenommen wird. Wenn Du jetzt programmatisch Datensätze einfügen / löschen willst, brauchst Du nur die entsprechende Aktion mit der OC durchzuführen und die (fürchterliche) "AnzeigeAktualisieren"-Funktion kann entfallen.
Das Zufügen eines Datensatzes zu der OC gehört jetzt natürlich in die Klasse ViewModel, in der Du noch einen 'Ersatz' für das Button-Click-Ereignis brauchst. Dazu bindest Du die "Command"-Eigenschaft des Buttons z. B. an die ViewModel-Eigenschaft:
ICommand AddCommand { private set; get; }
In dessen Execute-Methode kannst Du einfügen (oder löschen in einem DeleteCommand). Den zu löschenden Eintrag (den aktuellen Datensatz) findest Du übrigens ohne weiteres Zutun in "CurrentPerson".Die wenigen noch fehlenden Dinge findest z. B. beim "RelayCommand" von Laurent Bugnions "MVVM light". Außerdem schaue Dir das interface INotifyPropertyChanged an; dieses wird benötigt, wenn eine programmatische Änderung z. B. an einem Vornamen dem UI mitgeteilt werden soll.
Bei der komplexeren Personenliste ist wohl das größte Problem: wie stelle ich den "Chef" dar bzw. wie lasse ich ihn bearbeiten. Wenn die Bearbeitung bloß im Auswählen aus einer Liste Chefs besteht, kann recht einfach eine ComboBox dafür verwendet werden (das DataGrid stellt dafür eine "DataGridTemplateColumn" bereit). Für umfangreichere Editieraktionen ist sicher ein eigenes UI gerechtfertigt.
Gruß
Jürgen- Bearbeitet Jürgen Röhr Dienstag, 25. Oktober 2011 19:36 falsche namespace Darstellung
- Als Antwort markiert Robert Breitenhofer Dienstag, 8. November 2011 12:19
Dienstag, 25. Oktober 2011 19:32