2016-05-26 4 views
1

Ich versuche, mehrere ComboBoxen mit Daten aus einem bestimmten Datensatz gefüllt zu bekommen. Ich kann eine von ihnen richtig funktionieren lassen, aber ich denke, dass ein konzeptioneller Fehler mich daran hindert, dass der zweite richtig funktioniert. Ich habe verschiedene Threads nach SelectedItem, SelectedValue und SelectedIndex durchsucht und versucht, meinen Code nach der bereitgestellten Anleitung zu gestalten. Offensichtlich mache ich etwas falsch, aber nicht sicher was. Ich bin sehr ein Neuling mit allem, was ich gelernt habe, aus dem Internet autodidaktisch gelernt.MVVM ComboBox SelectedIndex vs. SelectedItem

Ich verwende ein Entity Framework 6 Database First Datenmodell. Ich habe eine Tabelle (Master), die einen Fremdschlüssel zum Verknüpfen mit der Schicht und einen anderen für die Personal-Tabellen hat. Die Shift-Tabelle hat die Felder ShiftId (PK), für die Identity auf true gesetzt ist und Shift, die nur eine Zeichenkette ist. Die Personaltabelle hat PersonalityId (PK), deren Identität auf "false" gesetzt ist (ich beziehe die IDs manuell von woanders aus) und Felder für den Vor- und Nachnamen.

Der gewünschte Ablauf meines Projekts ist: 1) Holen Sie den aktuellen Datensatz, 2) Füllen Sie die Shift ComboBox, 3) Zeigen Sie die mit dem aktuellen Datensatz verknüpfte Schicht, 4) Füllen Sie die Personal ComboBox, 5) Zeigen Sie die zugehörige Person an mit dem aktuellen Datensatz, 6) Speichern Sie alle Änderungen am Datensatz (Änderungen durch Auswahl eines anderen Wertes für eine der ComboBoxen).

Mein ViewModel verwendet INotifyPropertyChanged, und ich denke, ich habe dies korrekt implementiert, da die Shift ComboBox funktioniert.

1) Der gewünschte Datensatz funktioniert einwandfrei. Es wird dann als "CurrentRecord" gespeichert

2) Auffüllen der Shift ComboBox funktioniert gut.
In meinem Modell ich habe:

private ICollection<Gen_All_Shift> shiftList; 
    public ICollection<Gen_All_Shift> GetShiftList() 
    { 
     shiftList = context.Gen_All_Shift.OrderBy(p => p.ShiftId) 
              .ToArray(); 
     return shiftList; 
    } 

In meinem Ansichtsmodell Ich habe:

public ICollection<Gen_All_Shift> ShiftList 
    { 
     get { return context.GetShiftList(); } 
    } 

    private Gen_All_Shift selectedShift; 
    public Gen_All_Shift SelectedShift 
    { 
     get { return selectedShift; } 
     set 
     { 
      if (value != selectedShift) 
      { 
       selectedShift = value; 
       NotifyPropertyChanged("SelectedShift"); 
      } 
     } 
    } 

Dann wird die XAML ist:

 <ComboBox x:Name="cboShift" 
      ItemsSource="{Binding ShiftList}" 
      DisplayMemberPath="Shift" 
      SelectedIndex="{Binding CurrentRecord.ShiftIdFk, 
          UpdateSourceTrigger=PropertyChanged}" /> 

3) Anzeige der aktuelle Schicht funktioniert solange ich die Bindung an SelectedIndex habe. Wenn ich SelectedItem oder SelectedValue verwende, ist die ComboBox leer, wenn der Bildschirm geladen wird. (Ich habe auch versucht, an SelectedShift.ShiftId zu binden, aber das gibt mir nicht die gewünschten Ergebnisse.) SelectedIndex ermöglicht mir, die Auswahl zu ändern und ermöglicht mir, die Änderungen in der tatsächlichen Datenbank ordnungsgemäß zu speichern. Ich bin mir nicht sicher, was ich falsch mache, was verhindert, dass SelectedItem oder SelectedValue funktioniert. Ich verstehe das nicht, was dazu führt, dass ich Probleme mit der Personal Combobox habe, glaube ich.

4) Füllen der Personal ComboBox funktioniert.

In meinem Modell ich habe:

private ICollection<Personnel_All_PersonnelList> personnelList; 
    public ICollection<Personnel_All_PersonnelList> GetPersonnelList() 
    {    
      personnelList = context.Personnel_All_PersonnelList.Where(p=>p.Active == true) 
                   .OrderBy(p => p.LastName) 
                   .ThenBy(p => p.FirstName) 
                   .ToArray(); 
      return personnelList; 
    } 

In meinem Ansichtsmodell ich habe:

public ICollection<Personnel_All_PersonnelList> PersonnelList 
    { 
     get 
     { 
       return context.GetPersonnelList(); 
     } 
    } 

    private Personnel_All_PersonnelList selectedPerson; 
    public Personnel_All_PersonnelList SelectedPerson 
    { 
     get { return selectedPerson; } 
     set 
     { 
      if (value != selectedPerson) 
      { 
       selectedPerson = value; 
       NotifyPropertyChanged("SelectedPerson"); 
      } 
     } 
    } 

Da ist in meinem XAML ich habe:

<ComboBox x:Name="cboTechnician" 
      ItemsSource="{Binding PersonnelList}" 
      DisplayMemberPath="LastName" 
      SelectedIndex="{Binding CurrentRecord.PersonnelIdFk, 
          UpdateSourceTrigger=PropertyChanged}" /> 

5) Das Anzeigen der aktuellen Person funktioniert nicht, egal wie ich es versuche (SelectedIndex, SelectedItem, SelectedValue). Ich vermute, der Grund, warum SelectedIndex nicht so funktioniert wie bei der Verschiebung, liegt daran, dass die Indexnummer nicht korrekt mit der PersonalityId übereinstimmt, so dass das System keine Ahnung hat, welche tatsächlich ausgewählt ist.

6) Speichern der Änderungen an den Datensätzen funktioniert, wenn ich nur die Verschiebung ändern. Wenn ich eine Person in der Personal ComboBox auswähle und versuche zu speichern, bekomme ich eine Systemnull-Ausnahme. Ich nehme an, dass dies durch dasselbe Problem verursacht wird, das verhindert, dass SelectedIndex mit der Personal Combobox arbeitet.

Ich denke, wenn mir jemand in die richtige Richtung zeigen kann, warum ich die Bindung an SelectedItem nicht richtig funktionieren kann, werde ich herausfinden, wie man die Personal ComboBox repariert.

Antwort

1

Das erste, was Sie ausprobiert haben, war richtig, aber es gibt ein paar Dinge, die Sie im Stich lassen.

Zum Beispiel:

get { return context.GetShiftList(); } 

Im Allgemeinen ist dies nicht eine gute Idee. Jeder, der diese Eigenschaft aufruft, ruft den Datenbankaufruf jedesmal auf, was die Leistung beeinträchtigt und einfach nicht benötigt wird.

wäre eine bessere Idee, stattdessen zu nennen, ein Verfahren zur Last die ShiftList Eigenschaft, wie folgt aus:

public void ReloadShiftList() 
{ 
    //TODO: Your logic here 

    ShiftList = ... 
} 

Hinweis: Achten Sie darauf, INotifyPropertyChanged auf Ihrer ShiftList Eigenschaft, um die Aktualisierung zu implementieren anzeigen, wenn diese Eigenschaft geändert wird.

Wie für Ihre ComboBox, Bindung an die SelectedItem ist sicherlich die bevorzugte Methode. Der Grund, warum der ausgewählte Artikel leer beim ersten Laden war, war, weil SelectedShift auf Null gesetzt wurde. Um dies zu beheben, müssen Sie einfach SelectedShift einstellen, nachdem Sie die ShiftList geladen haben.

ShiftList = ... 
SelectedShift = ShiftList.FirstOrDefault(); 

Durch die SelectedShift zum .FirstOrDefault() der ShiftList Einstellung, werden Sie garantieren, dass es immeretwas im ComboBox ausgewählt werden (es sei denn, es keine Elemente in der ShiftList sind).

Schließlich Ihre Bindung würde wie folgt aussehen:

<ComboBox ItemsSource="{Binding ShiftList}" 
      SelectedItem="{Binding SelectedShift}" 
      ... /> 
0

@Mike Eason - Danke, das gab mir, was ich brauchte!

Die Ansichtsmodell für die Verschiebung sieht nun wie folgt aus:

private ICollection<Gen_All_Shift> shiftList; 
    public ICollection<Gen_All_Shift> ShiftList 
    { 
     get { return shiftList; } 
     set { shiftList = value; NotifyPropertyChanged("ShiftList"); } 
    } 

    private Gen_All_Shift selectedShift; 
    public Gen_All_Shift SelectedShift 
    { 
     get { return selectedShift; } 
     set { selectedShift = value; NotifyPropertyChanged("SelectedShift"); } 
    } 

    public void LoadShiftList() 
    { 
     ShiftList = context.GetShiftList(); 
     SelectedShift = ShiftList.Where(p => p.ShiftId == CurrentRecord.ShiftIdFk) 
           .FirstOrDefault(); 
    } 

Mit einem Aufruf der LoadShiftList() im Ansichtsmodell Konstruktor.

Dann wird die XAML hat nun die verbindlichen an die SelectedItem nach Wunsch:

 <ComboBox x:Name="cboShift" 
      ItemsSource="{Binding ShiftList}" 
      DisplayMemberPath="Shift" 
      SelectedItem="{Binding SelectedShift}" /> 

Zuvor ich SelectedShift.ShiftId == CurrentRecord.ShiftIdfk gesetzt hatte versucht. Das gab mir eine Null-Ausnahme. Wenn ich darauf hinwiese, den .FirstOrDefault() zu verwenden, bin ich wieder auf dem richtigen Weg. Danke noch einmal.