Laden...

WPF Databinding wenn Property aus einer Liste besteht

Erstellt von Stanicher vor 3 Jahren Letzter Beitrag vor 3 Jahren 935 Views
S
Stanicher Themenstarter:in
9 Beiträge seit 2018
vor 3 Jahren
WPF Databinding wenn Property aus einer Liste besteht

Guten Abend an alle,
ich habe mal wieder ein kleines Problem.
Ich versuche mich gerade an einem WPF-Projekt,
darin eine Liste mit verschiedenen Elementen, eine Property des Elements ist wiederum eine Liste, die ich nun als ObservableCollection an ein ListView gebunden habe. Angezeigt wird es, aber beim hinzufügen eines Elementes wird dieses nicht aktualisiert.

[Wegen der Übersichtlichkeit habe ich den Code Salat entfernt.]

Ich hoffe die Informationen reichen, um mir einen Schups in die richtige Richtung zu geben 😁

Schönen Abend euch allen.

5.657 Beiträge seit 2006
vor 3 Jahren

Kannst du bitte den Quelltext auf das Wesentliche reduzieren? Wo erstellst du die Liste und wo fügst du das Element zu der Liste hinzu?

Ansonsten schau mal in diesen Artikel: [Artikel] MVVM und DataBinding

Weeks of programming can save you hours of planning

S
Stanicher Themenstarter:in
9 Beiträge seit 2018
vor 3 Jahren

Guten Morgen,
den Artikel bin ich schon einmal durch gegangen, sonst wäre ich noch nicht mal so weit. Danke für die Mühe, er ist sehr verständlich. 👍

Ich habe es jetzt auch nochmal durch geschaut und noch etwas probiert, bin aber irgendwie nicht voran gekommen. Ich poste den jetzigen Stand, wie es meiner Ansicht (offensichtlich die falsche) nach funktionieren sollte.

Ich habe eine Liste von Elementen "vmo_Zutat", die folgende Liste von Elementen "vmo_Deklaration_List" beinhaltet::


public class vmo_Zutat : vmo_Base
{
private vmo_DeklarationList _deklarationen;
.....
public vmo_DeklarationList Deklarationen
        {
            get { return _deklarationen; }
            
        }
}

Die Liste wird mit Elementen aus der Datenbank gefüllt:


public class vmo_Zutat : vmo_Base
    {
....
foreach(var item in _classObject.Deklaration2Zutaten)
            {
                var element = query.GetData(item.DeklarationID);
                _deklarationen.AddItem(element);
                
            }
...
}            

Soweit funktioniert es, da die so eingefügten Elemente angezeigt werden.

Im Listenelement "vmo_DeklarationList" werden weitere Elemente eingefügt (diese Funktion wird auch bei der initialisierung verwendet):


public class vmo_DeklarationList:vmo_Base
    {
....
 public void AddItem(dbo_Deklaration toadd)
        {
            _currentValue.Add(new vmo_Deklaration(toadd));
            HasChanged = true;
            CollectionChanged("Value");
        }
}

nach dem einfügen wird "HasChanged" auf true gesetzt und "CollectionChanged" aus der Basisklasse "vmo_base" aufgerufen. Hier bin ich mir nicht sicher, ob der Aufruf von "CollectionChanged("Value");" an der richtigen Stelle ist, da ja jetzt meiner Ansicht nach das ListView wissen sollte, dass sich etwas geändert hat.

"Value" ist das Element, an das das ListView gebunden wird:


 public class vmo_DeklarationList:vmo_Base
    {
private ObservableCollection<vmo_Deklaration> _currentValue;
....
public ObservableCollection<vmo_Deklaration> Value
        {
            get { return _currentValue; }            
        }
}

"vmo_Base" sieht folgendermaßen aus:


public abstract class vmo_Base:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void SetProperty<T>(ref T storage, T value, [CallerMemberName] string property = null)
        {
            if (Object.Equals(storage, value)) return;
            storage = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

        protected void CollectionChanged( string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

Hier das Binding auf das ListView:


Grid x:Name="Grd_Detail_List_mid" Grid.Column="1" DataContext="{Binding SelectedItem, ElementName=Lst_Elemente}">                   
                    <ListView x:Name="Lst_Elemente_Copy" SelectionMode="Single" Margin="0,0,0,0" Background="#FFE5E6CD" ItemsSource="{Binding Deklarationen.Value}" HorizontalContentAlignment="Left" ScrollViewer.CanContentScroll="True" Grid.Row="1" >
                        <ListView.View>
                            <GridView>                                
                                <GridViewColumn DisplayMemberBinding="{Binding Bezeichnung.Value}" Header="Bezeichnung" Width="180"/>
                                <GridViewColumn DisplayMemberBinding="{Binding Schluesselzahl.Value}" Header="Schlüssel" Width="70"/>
                            </GridView>
                      </ListView.View>
            </ListView>
</Grid>

5.657 Beiträge seit 2006
vor 3 Jahren

Ich kann noch nicht nachvollziehen, an welcher Stelle es jetzt klappt, und an welcher Stelle nicht. Du sagst, daß nachträglich hinzugefügte Elemente nicht mehr in der Liste angezeigt werden? Werden die auch über die AddItem-Methode hinzugefügt?

Die CollectionChanged-Methode ist allerdings überflüssig, die ObservableCollection-Klasse hat alle Benachrichtigungen bereits eingebaut.

Merkwürdig ist auch, daß du den DataContext des Grids an das ausgewählte Element bindest, welchen Zweck soll das haben? Normalerweise muß man nur einmal bei der Initialisierung den DataContext des Fensters auf das MainViewModel setzen. Und wenn der nachträglich geändert wird, dann funktionieren die bestehenden Bindings nicht mehr.

Du könntest auch mal schauen, ob es einen Fehler im Ausgabefenster gibt, siehe dazu [Artikel] MVVM und DataBinding (Abschnitt Debugging).

Die Benennung deiner Klassen ist auch etwas verwirrend, normalerweise verwendet man keine Prefixe, sondern die ViewModels heißen einfach EmployeeViewModel oder CompanyViewModel oder so. Siehe dazu auch: [Artikel] C#: Richtlinien für die Namensvergabe

Und Datenbankabfragen sollten eigentlich nicht im ViewModel stattfinden, das würde ich auch mal noch an die richtige Stelle auslagern. Siehe dazu: [Artikel] Drei-Schichten-Architektur

Weeks of programming can save you hours of planning

S
Stanicher Themenstarter:in
9 Beiträge seit 2018
vor 3 Jahren

Guten Morgen,
genau, die nachträglich eingefügten Elemente werden nicht angezeigt. Ich verwende die AddItem Methode zum einfügen.

Das mit dem DataContext habe ich wohl aus irgendeinem Tutorial, kann aber leider nicht mehr nachvollziehen welches genau und warum das überhaupt so ist. Ich habe aber 2 Grids mit diesem DataContext und ich denke jetzt, dass hier auch das Problem liegt.

Ich darf das nicht so lösen, sondern muss das selectedItem im ViewModel als Property angeben um dann alle Detail-Elemente wie Textboxen und eben auch die Liste darauf binden.

Ich muss auch dazu sagen, das die mein erster Versuch mit dem MVVM ist, somit werde ich das ganze Projekt wohl mit Hilfe der Links und der Hinweise die du gepostet hast einfach nochmal neu aufbauen.

Sollte es dann auch nicht funktionieren werde ich mich an dieser Stelle noch einmal melden.

Vorerst vielen Dank für die Antworten und noch eine schöne Zeit.