2016-07-28 30 views
0

Ich habe eine ComboBox an eine Liste von Menschen in einem einfachen ViewModel gebunden. Das SelectedPerson wird in dem Konstruktor des ViewModel festgelegt aber wenn ich die Anwendung ausführen, wird das ComboBox nicht mit seinem Anfangswert festgelegt. Was mache ich falsch?ComboBox nicht autoselecting Anfangswert

Beachten Sie, dass zwei Instanzen der Klasse als gleich angesehen werden sollten, wenn sie die gleiche ID haben.

WICHTIG: Ich kann die nicht ändern, um Equals (es ist dritte Partei) zu überschreiben.

Die einzige Option, die ich bisher gesehen habe, ist, das Adaptermuster zu verwenden, um die Instanzen dieser Klasse zu umhüllen und eine benutzerdefinierte Equals-Methode dort zu implementieren.

Ich glaube, dass sollte es eine bessere Methode, die native zu WPF ist, um Elemente aus einer Liste von einer Art von "Schlüssel" übereinstimmen. In meinem Fall stammen die Liste der Elemente und das ausgewählte Element aus verschiedenen Quellen, weshalb sie eine Id-Eigenschaft haben, die als Primärschlüssel fungiert.

Bitte schauen Sie sich den Code an, den ich mit SelectedValue und SelectedValuePath gespielt habe, aber nichts funktioniert.

<Window x:Class="Test.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:vm="clr-namespace:Test" 
     mc:Ignorable="d" 
     x:Name="Root" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <vm:MainViewModel /> 
    </Window.DataContext> 
    <ComboBox ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson}" SelectedValuePath="Id" 
       DisplayMemberPath="Name" 
       SelectedValue="{Binding SelectedPerson}" /> 
</Window> 

Und das Ansichtsmodell als Datacontext:

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     SelectedPerson = new MyPerson { Name = "Mary", Id = 1 }; 
    } 

    public MyPerson SelectedPerson { get; set; } 

    public IEnumerable<MyPerson> People { get; } = new List<MyPerson>() 
    { 
     new MyPerson() {Name = "Mary", Id = 1 }, 
     new MyPerson() {Name = "John", Id = 2 }, 
    }; 
} 

public class MyPerson 
{ 
    public string Name { get; set; } 
    public int Id { get; set; } 
} 
+1

1) Zuerst verwenden Sie 'INotifyPropertyChanged' Schnittstelle für Ihr MainViewModel. 2) Fügen Sie "OnPropertyChange" (oder besser: Sie werden es nennen) zu "selectedPerson" Setter hinzu. – Shakra

+0

1) Verwenden Sie zuerst die 'INotifyPropertyChanged' Schnittstelle für Ihr MainViewModel. 2) Fügen Sie 'OnPropertyChange' (oder besser, wie Sie es nennen) zu' selectedPerson' Setter 3) Sie verwenden 'SelectedValue' auf eine falsche Weise -> [Article] (http://www.codeproject.com/Articles/ 671544/Understanding-SelectedValue-SelectedValuePath-Sele) 4) Verwenden Sie besser 'SelectedItemIndex', um zu prüfen, welches Element ausgewählt ist. Atm Sie liefern "SelectedPerson" und "People" Liste mit verschiedenen Objekten mit dem Namen Mary und Id = 1, die auch einige Probleme bringen könnte. * Konnte nicht bearbeiten wegen 5mins Grenze)) * – Shakra

+0

@Shakra In diesem Fall muss ich die Schnittstelle nicht implementieren. Der Wert sollte beim ersten Laden des Combos ohne Änderungsbenachrichtigung abgefragt werden. – SuperJMN

Antwort

0

ändern

public MainViewModel() 
{ 
    SelectedPerson = new MyPerson { Name = "Mary", Id = 1 }; 
} 

Um

public MainViewModel() 
{ 
    SelectedPerson = People.ElementAt(0); 
} 

Oder wenn ou wollen nach Name:

public MainViewModel() 
{ 
    SelectedPerson = People.First(x=> x.Name=="Mary"); 
} 
1

Das Problem ist, dass das neue Objekt, das Sie

SelectedPerson = new MyPerson { Name = "Mary", Id = 1 }; 

sind nicht ‚die gleichen wie in der Liste hier erstellen, damit die Equals Methode False in allen Fällen zurückkommen würde!

Wie jemand anderes bereits vorgeschlagen, müssen Sie das reale Objekt erhalten, indem Sie diese in der Liste enthalten ist:

public MainViewModel(){ 
    SelectedPerson = People.First(x=> x.Name.Equals("Mary")); //Or: x.Id == 1 
} 

Aber es gibt auch eine andere Lösung: Sie können die Equals Funktion in Ihrem MyPerson Klasse überschreiben , so dass jeder Fall mit dem gleichen Name und/oder Id in der Tat als die gleiche Person gesehen werden würde.

EDIT

Wie Sie Viewmodel in Ihrem Projekt verwenden, wäre es besser, wenn Sie auch ein Ansichtsmodell für die MyPerson Klasse haben. Es würde Ihre Probleme lösen und machen Sie Ihr Design besser!

+0

Sorry, ich habe vergessen zu sagen, dass MyClass eine Drittanbieterklasse ist, die ich nicht ändern kann. Ich habe die Frage modifiziert. – SuperJMN

+1

Sie können immer noch die erste Lösung verwenden, um das gewünschte Ergebnis zu erzielen. WPF weiß nicht, dass ein Objekt das gleiche ist, wenn die Eigenschaftswerte sind. Es ist einfacher, wenn Sie MVVM verwenden. Ihr ViewModel wäre (wie Sie in Ihrer Antwort sagten) eine Art Wrapper für Ihr reales Objekt. –

+1

Es wäre besser, wenn Sie sowieso ein ViewModel für Ihr MyPerson-Objekt hätten! –