Laden...

Wie binde ich auf eine Collection eines Properties im ViewModel?

Erstellt von Mahu83 vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.234 Views
M
Mahu83 Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren
Wie binde ich auf eine Collection eines Properties im ViewModel?

Moin zusammen,

ich erstelle gerade meine erste wirkliche WPF Anwendung mit MVVM Modell. Bestimmt kennt Google eine Antwort auf meine Frage. Mir fehlen aber scheinbar schlichtweg die richtigen Schlagwörter. Jetzt hoffe ich auf Eure versierte Hilfe.

In meinem Model gibt es die Klasse Personen. Diese hat eine 1:n Beziehung an die Klasse Termine. Eine Person hat also mehrere Termine.

In meinem ViewModel erzeuge ich eine ObservableCollection von Personen. Diese Property ist in der View an die Itemssource einer Listbox gebunden. Darstellung der Listbox ist ein UserControl, welches ich per Datatemplate eingebunden habe. Das Usercontrol hat keinen Datacontext angegeben und erbt, nach meinem Wissen, somit den Datacontext der View. Soweit funktioniert alles.

Ich möchte jetzt in den Usercontrols eine Liste mit den Terminen jeder Person anzeigen. Und genau hier komme ich mit der Bindung der Itemssource nicht weiter. Wie lautet der entsprechende XAML Befehl dazu?

Ich hoffe, dass ich mein Problem gut erklären konnte. Wenn Infos fehlen, schiebe ich diese natürlich gerne hinterher.

Vielen Dank und beste Grüße
Mahu83

P
441 Beiträge seit 2014
vor 4 Jahren

Hi,

sind die Termine direkt an das Person Objekt als Property gebunden (a) oder hast du eine extra Collection mit Terminen (b)?

Gibt mehrere Lösungen, deine ListBox hat eine SelectedItem Property, welche du an eine Property im ViewModel vom Typ Person binden kannst. Wenn sich diese ändert (im Setter),

a) deine Termindarstellung einfach an das SelectedItem der Listbox direkt im XAML binden
b) kannst du einfach deine Termine filtern und in einer extra Collection anbieten

M
Mahu83 Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren

Hallo Papst,

es gibt eine Variable Anzahl an Personen. Jede Person wird in einem "Dashboard" als Karte dargestellt. und auf jeder dieser Karten ist eine Auflistung der Termine zu dieser Person. Die Karte ist das UserControl und erbt vom MainViewModel. Hat also kein eigenes VM Jetzt würden doch bei

a) nur die Termine der Selektierten Person dargestellt werden
b) nur eine ObservableCollection aller Termine der gezeigten Personen entstehen, da ja nicht jedes Control ein eigenes VM mit eigenen Properties hat.

Die Klassen Personen und Termine sind automatisch im Entity Framework aus der Datenbank erstellt worden. Termine hängen als public virtual ICollection<Termine> in der Personenklasse.

Im VM erstelle ich eine ObservableCollection der Personen und hatte jetzt gedacht das ich irgendetwas in der Art wie {Binding Personen.Termine} oder mit einem ähnlichen Befehl in XAML arbeiten kann, um dies an die ItemsSource der Listbox auf der Karte zu hängen.

Aus dem VM

 private ObservableCollection<tabUser> myPersons;
        public ObservableCollection<tabUser> Persons
        {
            get { return myPersons; }
            set { myPersons = value; RaisePropertyChanged("Persons"); }
        }


        private void FindPerson()
        {
            myDatacontext = new CBBDataModel();
            string myUGroup = mySelectedUserGroup.ID;
            if(myUGroup == null || myUGroup == "All")
            {
                myUGroup = "";
            }

            var myPerson = from Person in myDatacontext.tabUser
                           where (Person.KNr.Contains(myFiltertext)
                           || Person.UsrLastName.Contains(myFiltertext))
                           && Person.GroupID.Contains(myUGroup)
                           orderby Person.UsrLastName
                           select Person;

            Persons = new ObservableCollection<tabUser>();

            foreach(tabUser person in myPerson)
            {

                Persons.Add(person);
            }

        }

Die Termine hängen ja durch die Beziehung der beiden Tabellen schon jeweils hinter den einzelnen Personen Elementen in der ObservableCollection Personen.

Aus der View

           
<Window x:Class="CBB.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ViewModels="clr-namespace:CBB.ViewModels"
        xmlns:Converters="clr-namespace:CBB.Converters"
        xmlns:Controls="clr-namespace:CBB.Controls"
        mc:Ignorable="d"
        
        Title="CBB" Height="800" Width="1200">

    <Window.DataContext>
        <ViewModels:MainViewModel/>
    </Window.DataContext>
    

    <Grid>
        <Grid Name="ContentPanel" Margin="0">
       
            <ListBox ItemsSource="{Binding Persons}" 
                     SelectedItem="{Binding SelectedPerson}"
                     Padding="0" BorderThickness="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Grid.ColumnSpan="4">

                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Controls:PersCard/>
                    </DataTemplate>
                </ListBox.ItemTemplate>

                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>

            </ListBox>

        </Grid>
       
    </Grid>
</Window>

Aus dem UserControl

<UserControl
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            x:Class="CBB.Controls.PersCard"
            mc:Ignorable="d">

    <Grid>
        
        <!--....
        Irgendwelche Controls, die hier jetzt nichts zur Sache tun ......
        ....-->
        
        
        <!--Was muss hier gebunden werden?-->
        <ListBox ItemsSource="{Binding Persons/tabUserTermine}" Height="100"/>
    </Grid>

</UserControl>

In welche Richtung muss ich da recherchieren? RelativeSource und FindAnchestor oder geht das nur über Binding Path?

Vielen Dank und beste Grüße

Mahu83

W
955 Beiträge seit 2010
vor 4 Jahren

Im VM erstelle ich eine ObservableCollection der Personen und hatte jetzt gedacht das ich irgendetwas in der Art wie {Binding Personen.Termine} Wieso? Person ist doch bereits der DataContext für das ItemTemplate wenn du eine Collection<Person> bindest.

M
Mahu83 Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren

Ja. Ich kann auch im UserControl auf die direkten Eigenschaften der Klasse Person zugreifen. Ich bekomme es nur nicht hin, auf die Klasse Termine zuzugreifen. Diese Tabelle steht im Entity Framework ja in Beziehung zur Tabelle Person und hängt ja auch an den Instanzen der Personenklasse. Im Viewmodel komme ich da dran. Nur im Usercontrol fehlt mir einfach die richtige Zeile Code.

Wenn ich die Person direkt in das Itemtemplate der Listbox als Datatemplate schreibe klappt es übrigens. Dann bin ich eben direkt in der View und nicht im UserControl. Die Funktion ist gegeben ich würde nur gerne den entsprechenden XAML Code im UC halten, damit das ganze ein wenig "aufgeräumter" ist.

P
441 Beiträge seit 2014
vor 4 Jahren

Ich muss gestehen, mein WPF ist schon etwas her.
Ich hätte das vermutlich mit einem DataTemplate gelöst und gefilterte Termine in einer Property Collection bereitgestellt 😃

Vermutlich liegt aber Prinzipiell aber da auch das Problem. Du verwendest in der View-Schicht die Datenbank Entitäten. Würdest du eine Projektion erzeugen, bei der nur eine Personenliste existiert und das Personen-Model bereits eine eigene Collection mit Terminen hätte, würde alles funktionieren, denn du kannst ja auch die Properties der Personen Instanz zugreifen.