WPF ListBox in ListBox
-
Firefighter schrieb:
Kann mir jemand sagen wo der Fehler liegt?
Schau mal ganz genau, wo Mr Evil die Variable Items deklariert/definiert und wie er das Binding realisiert hat. Bei dir sieht das jedenfalls ziemlich anders aus und mit dem was du zeigst, kann ich mir nicht vorstellen, dass dies funktionieren wird.
Zudem, wie ist das eigentlich, wäre nicht
Name
die richtige Eigenschaft, stattx:Name
um einen Namen für das Objekt zu definieren?x:Name
ist doch nur für Ressourcen gedacht.Grüssli
-
Sorry Knuddlbaer, hast Recht, vergesses jedes mal. Der Binded in dem Sinne nicht Richtig, das er die Daten einfach nicht anzeigt.
@Dravere. Ich glaube ist egal ob x:Name oder Name, beides ist möglich.
-
Hmm @Dravere, so auf Anhieb weiß ich nicht was an meinem Falsch sein soll, ich meine ich setze den Datacontext von der Listview auf meine Collection, binde diese dann im XAML, um dann auf die einzelene Komponenten der Collection in meinen GridViewColums zuzgreifen, steh etwas aufem schlauch.
-
<ListView ItemsSource="{Binding}" x:Name="listview"><!-- Nur {Binding} --> <ListView.View> <GridView> <GridViewColumn Header="Datum" DisplayMemberBinding="{Binding Path=StartDatum}"/> <GridViewColumn Header="Betrag" DisplayMemberBinding="{Binding Path=Betrag}"/> <GridViewColumn Header="Beschreibung" DisplayMemberBinding="{Binding Path=Beschreibung}"/> <GridViewColumn Header="Art" DisplayMemberBinding="{Binding Path=TransaktionsArt}"/> </GridView> </ListView.View> </ListView>
Und ja, so sieht auch der Code von Mr Evil nicht aus. Ich hätte allerdings gedacht, dass dieser auch funktionieren würde, tut er aber nicht, nachdem ich es selber getestet habe
Der C# Code bleibt übrigens unverändert.
Grüssli
-
Korrekt, mein XAML Code sieht nun genauso aus, und mein C# Code sieht nun folgender MAßen aus.
public class Item { public ObservableCollection<Transaktion> Items = new ObservableCollection<Transaktion>(); } public partial class Mainform : Window { private ObservableCollection<Item> Items = new ObservableCollection<Item>(); public Mainform() { InitializeComponent(); Transaktion aktion1 = new Transaktion(Transaktion.Art.Sonstige, DateTime.Now); aktion1.Beschreibung = "test1"; aktion1.Betrag = 100; Transaktion aktion2 = new Transaktion(Transaktion.Art.Ausgabe, DateTime.Now); aktion2.Beschreibung = "test2"; aktion2.Betrag = 200; Transaktion aktion3 = new Transaktion(Transaktion.Art.Einnahme, DateTime.Now); aktion3.Beschreibung = "test3"; aktion3.Betrag = 300; Item item = new Item(); item.Items.Add(aktion1); item.Items.Add(aktion2); item.Items.Add(aktion3); Items.Add(item); listview.DataContext= Items; } }
Entspricht doch dem wie es Mr evil jebaut hatte oder irre ich mich?
-
Dravere schrieb:
Und ja, so sieht auch der Code von Mr Evil nicht aus. Ich hätte allerdings gedacht, dass dieser auch funktionieren würde, tut er aber nicht, nachdem ich es selber getestet habe
is doch logisch
ich hab das binding explizit zu einer liste gesetzt da ich davon aus ging das die daten in einer viewmodel im datacontext des fensters sitzen , dann bindet man auf ein feld der viewmodel
wenn man aber im code behind des fensters arbeitet und den datacontext der liste setzt kanns ja nicht funktionierendenn wenn der datacontext auf der liste ist , und das itemssource auf Items - sucht er Items _in_ der observablecollection , das ist natuerlich kaese fuer die hauptliste - dann kommt ein konstrukt das er Items in Items in Items sucht #gg
der code veraendert sich sozusagen leicht wenn man entweder mit der code behind arbeitet oder mit mvvm
hier mal beide varianten: (natuerlich hier im forum ausn kopf geschrieben , muss nicht funktionieren {o;)
MainView.xaml
<ListView ItemsSource="{Binding Items}"> <!-- die Items liste aus der MainViewModel vom DataContext des fensters --> <ListView.View> <GridView> <GridViewColumn> <GridViewColumn.CellTemplate> <DataTemplate> <ListView ItemsSource="{Binding Items}" x:Name="listview"> <!-- die Items von der Item klasse --> <ListView.View> <GridView> <GridViewColumn Header="Datum" DisplayMemberBinding="{Binding Path=StartDatum}"/> <GridViewColumn Header="Betrag" DisplayMemberBinding="{Binding Path=Betrag}"/> <GridViewColumn Header="Beschreibung" DisplayMemberBinding="{Binding Path=Beschreibung}"/> <GridViewColumn Header="Art" DisplayMemberBinding="{Binding Path=TransaktionsArt}"/> </GridView> </ListView.View> </ListView> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView>
Item.cs
public class Item { public ObservableCollection<Transaktion> Items = new ObservableCollection<Transaktion>(); }
MainViewModel.cs
class MainViewModel { private ObservableCollection<Item> Items = new ObservableCollection<Item>(); public MainViewModel() { Transaktion aktion1 = new Transaktion(Transaktion.Art.Sonstige, DateTime.Now); aktion1.Beschreibung = "test1"; aktion1.Betrag = 100; Transaktion aktion2 = new Transaktion(Transaktion.Art.Ausgabe, DateTime.Now); aktion2.Beschreibung = "test2"; aktion2.Betrag = 200; Transaktion aktion3 = new Transaktion(Transaktion.Art.Einnahme, DateTime.Now); aktion3.Beschreibung = "test3"; aktion3.Betrag = 300; Item item = new Item(); item.Items.Add(aktion1); item.Items.Add(aktion2); item.Items.Add(aktion3); Items.Add(item); } }
App.cs
protected overrice OnStartup() { MainView view = new MainView(); view.DataContext = new MainViewModel(); // <-- darum geht das {Binding Items} der ersten liste view.Show(); base.OnStartup(); }
wenn man in der code behind ist , also ohne mvvm arbeitet , und das datacontext zu der liste gibt muss man das binding leicht anpassen wie dravere das auch gemacht hat , sonst ist der code identisch
MainView.xaml
<ListView ItemsSource="{Binding}" x:Name="myList"> <!-- die Items werden gefunden da DataContext explizit gesetzt --> <ListView.View> <GridView> <GridViewColumn> <GridViewColumn.CellTemplate> <DataTemplate> <ListView ItemsSource="{Binding Items}" x:Name="listview"> <!-- die Items von der Item klasse --> <ListView.View> <GridView> <GridViewColumn Header="Datum" DisplayMemberBinding="{Binding Path=StartDatum}"/> <GridViewColumn Header="Betrag" DisplayMemberBinding="{Binding Path=Betrag}"/> <GridViewColumn Header="Beschreibung" DisplayMemberBinding="{Binding Path=Beschreibung}"/> <GridViewColumn Header="Art" DisplayMemberBinding="{Binding Path=TransaktionsArt}"/> </GridView> </ListView.View> </ListView> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView>
Item.cs
public class Item { public ObservableCollection<Transaktion> Items = new ObservableCollection<Transaktion>(); }
MainView.xaml.cs
class MainViewModel { private ObservableCollection<Item> Items = new ObservableCollection<Item>(); public MainViewModel() { Transaktion aktion1 = new Transaktion(Transaktion.Art.Sonstige, DateTime.Now); aktion1.Beschreibung = "test1"; aktion1.Betrag = 100; Transaktion aktion2 = new Transaktion(Transaktion.Art.Ausgabe, DateTime.Now); aktion2.Beschreibung = "test2"; aktion2.Betrag = 200; Transaktion aktion3 = new Transaktion(Transaktion.Art.Einnahme, DateTime.Now); aktion3.Beschreibung = "test3"; aktion3.Betrag = 300; Item item = new Item(); item.Items.Add(aktion1); item.Items.Add(aktion2); item.Items.Add(aktion3); Items.Add(item); myList.DataContext = Items; } }
-
@Firefighter,
Willst du eigentlich immernoch eine Liste in einer Liste haben? Wäre es nicht sinnvoller alles in eine ListView zu packen, eine weitere Kolonne dazu, welches das Datum der Überweisung beinhaltet und dann ein Sortierkriterium einbauen? Jeweils ein zusätzliches Sortierkriterium für die anderen Kolonnen würde auch nicht schaden.Vielleicht gäbe es sogar eine Möglichkeit, dass die unterschiedlichen Datumsbereiche farblich hervorgehoben werden. Könnte man über eine Abwechslung von Grau und Weiss erreichen.
Grüssli
-
stimmt - groups wuerde sich aber auch anbieten
-
Mr Evil schrieb:
stimmt - groups wuerde sich aber auch anbieten
Hab mir schnell Groups angeschaut, ich glaube das wäre für Firefighter definitiv die beste Lösung. Geil was man damit anstellen kann
Kann man eigentlich sowas auch über die WinAPI realisieren?
Grüssli
-
Groups...hmmm das hört sich interessant an.Da werd ich mal ein Auge reinwerfen.Wenn ich fragen habe, weiß ich ja wo ich wieder fragen kann :p
-
Seh ich das richtig das man die "Groups" nicht mit XAML binden kann?Habe ausschließlich C# beispiele gefunden und das wollt ich eigentlich nicht unbedingt
-
Firefighter schrieb:
Seh ich das richtig das man die "Groups" nicht mit XAML binden kann?Habe ausschließlich C# beispiele gefunden und das wollt ich eigentlich nicht unbedingt
Geh mal in den Document Explorer, dort zur .Net Klassen Bibliothek, dann zu System.Windows.Controls, dann die Klasse ListView auswählen. Unter "More Code" gibt es ein "How to: Group Items in a ListView That Implements a GridView". Dieses Beispiel verwendet ausschliesslich XAML.
Hier auch in der MSDN auf dem Netz:
http://msdn.microsoft.com/en-us/library/ms754027.aspxGrüssli
-
Wie Peinlich, danke dir Dravere
-
genau
wollte grad n beispiel raus suchen - hab bei mir in nem projekt auch schon listboxen gruppiert mit expandern (man kann dadurch die einzelnen gruppen auf und zu klappen
-
Könntest du das eventuell mal Posten?Wäre interessant zu wissen wie man das Professionell macht?
-
ok
man kann ja eigentlich nichts falsch machen - solang es klar lesbar ist und gut wartbar ist es gut - "professionell" hin oder her #ggma gugg
ich hatte das glaub ich ziemlich uebernommen von der msdn da ich genau so auch brauchte #gg
<Window.Resources> <!-- ToDo: move the CollectionViewSource to the ListBox direct --> <CollectionViewSource x:Key="UserSource" Source="{Binding Path=Users}"> <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="Mode" /> </CollectionViewSource.GroupDescriptions> <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="Name" Direction="Ascending" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource> </Window.Resources> . . . <ListBox ItemsSource="{Binding Source={StaticResource UserSource}}" SelectedItem="{Binding CurrentUser}"> <ListBox.GroupStyle> <GroupStyle> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Margin" Value="0,0,0,5"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupItem}"> <Expander IsExpanded="True"> <Expander.Header> <DockPanel> <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,10,0" /> <TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}"/> </DockPanel> </Expander.Header> <Expander.Content> <ItemsPresenter /> </Expander.Content> </Expander> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> </GroupStyle> </ListBox.GroupStyle> </ListBox>
ich hab noch auf meiner todo stehen die collectionviewsources von den resourcen direkt in die liste zu packen , hatte bei der erstem implementation keine zeit das ich es schnell zusammen geschustert hatte {hab das ToDo: mark aber eben erst wieder gefunden #gg}
ich mags nicht sowas unnoetig auseinander zu ziehen {weil man es nur an einer stelle braucht}btw , die namen user und mode sieht zwar sehr nach demo aus , aber ich hab wirklich eine user liste #gg
so - jetzt erstma arbeits musik ein schalten - muss noch was schaffen {=
http://www.youtube.com/watch?v=85mLq4vH_mc
http://www.youtube.com/watch?v=P84eAzdmHkw