C# 从对象设置组合框的SelectedItem

C# 从对象设置组合框的SelectedItem,c#,wpf,entity-framework,mvvm,combobox,C#,Wpf,Entity Framework,Mvvm,Combobox,我正在Visual Studio 2015中构建一个MVVM Light WPF应用程序,Entity Framework 6 EF提供数据。我有一个组合框,显示某人需要进行药物测试的原因,如下所示: <ComboBox ItemsSource="{Binding ReasonsForTest}" SelectedItem="{Binding Path=ReasonsForTestVm, UpdateSourceTrigger=Proper

我正在Visual Studio 2015中构建一个MVVM Light WPF应用程序,Entity Framework 6 EF提供数据。我有一个组合框,显示某人需要进行药物测试的原因,如下所示:

<ComboBox ItemsSource="{Binding ReasonsForTest}"
    SelectedItem="{Binding Path=ReasonsForTestVm,
                     UpdateSourceTrigger=PropertyChanged}"
    DisplayMemberPath="Description" />
我有一个数据服务类,它包含以下代码来获取ComboBox有效值的数据:

组合框具有正确的数据;然而,当应用程序启动时,它没有选择正确的值-加载时显示为空白。SelectedItem ReasonsForTestVm也是该类类型的ReasonForTestViewModel,并从数据库中为此人填充一项。我已经仔细阅读了代码,以确保ReasonsForTestVm具有正确的数据,而且它确实如此

以下是ReasonsForTestVm的属性:

我做错了什么?我快要疯了


更新:很抱歉上面属性中的名称令人困惑。已修复。

任何扩展的WPF项控件(如ComboBox和ListBox)都有两个经常结合使用的属性:ItemsSource和SelectedItem

将集合绑定到ItemsSource时,UI中将显示这些项的表示形式。每个表示都绑定到绑定到ItemsSource的集合中找到的实例。例如,如果您正在使用DataTemplate创建该表示,您将在每个表示中发现DataContext将是集合中的实例之一

当您选择其中一个表示形式时,SelectEditeProperty现在将保存绑定到该表示形式的集合中的实例

通过用户与UI的交互,这一点非常有效。但是,当以编程方式与这些控件交互时,有一个重要的警告

将这些属性绑定到视图模型中的类似属性是一种非常常见的模式

public class MuhViewModel
{
    public MuhItems[] MuhItems {get;} = new[]{ new Item(1), new Item(2) };

    // I don't want to show INPC impls in my sample code, kthx
    [SuperSlickImplementINotifyPropertyChangedAttribute]
    public MuhSelectedItem {get;set;}
}
必然

<ComboBox ItemsSource="{Binding MuhItems}"
          SelectedItem="{Binding MuhSelectedItem}" />
用户界面不会改变。选择器看到ItemsSource已更改,是的,但在ItemsSource集合中找不到该实例。它不知道值为2的项的一个实例等同于值相同的任何其他项。所以它什么也不做。对于真正发生的事情来说,这有点简单化了。你可以直接进行反编译,自己看看。它在那里变得非常复杂

在这种情况下,您应该使用绑定到ItemsSource的集合中的实例更新SelectedItem。在我们的例子中

var derp = muhViewModel.MuhItems.FirstOrDefault(x => x.MuhValue == 2);
muhViewModel.MuhSelectedItem = derp;

旁注,在调试会话中跟踪实例时,使用Visual Studio的功能会有所帮助。

ItemsSource={Binding ReasonsForTest}-什么是ReasonsForTest?它是ReasonForTestViewModel的集合吗?我们可以看到该属性和ReasonsForTestVm属性的声明吗?您说ReasonsForTest类是这样的,但随后您有了ReasonForTestViewModel的定义。这是打字错误吗?SelectedItem应该始终是ItemsSource的实例。如果SelectedItem中的实例不在ItemsSource中,UI将不会按预期更新。不,不是同一类型。仔细阅读:ItemsSource中的实例必须在绑定到SelectedItem的集合中找到。例如,如果SelectedItem绑定到公共项[]Foo{get;}=new[]{new Item,new Item};,对于SelectedItem,必须使用Foo中的一项:SelectedItem=Foo[0];。如果选择EdItem=new Item;,即使它们是等效的,UI也不会像预期的那样运行,因为在ItemsSource中找不到SelectedItem中的实例。它等效于其中一个实例,但不是该实例。@will,现在我明白了:因此SelectedItem必须是填充组合框的OC中的确切实例之一。现在它终于点击了!因此,我必须在ItemsSource OC中搜索应该选择的项目,然后将该项目传递给SelectedItem。是的,尝试一下,看看这是否是您的问题。抱歉,我没有足够的时间来检查您的代码,但我确实认为这可能是问题所在。
public ReasonForTestViewModel ReasonForTestVm
{
    get
    {
        return _reasonForTestVm;
    }

    set
    {
        if (Equals(value, _reasonForTestVm)) return;
        _reasonForTestVm = value;
        RaisePropertyChanged();
    }
}
public class MuhViewModel
{
    public MuhItems[] MuhItems {get;} = new[]{ new Item(1), new Item(2) };

    // I don't want to show INPC impls in my sample code, kthx
    [SuperSlickImplementINotifyPropertyChangedAttribute]
    public MuhSelectedItem {get;set;}
}
<ComboBox ItemsSource="{Binding MuhItems}"
          SelectedItem="{Binding MuhSelectedItem}" />
muhViewModel.MuhSelectedItem = new Item(2);
var derp = muhViewModel.MuhItems.FirstOrDefault(x => x.MuhValue == 2);
muhViewModel.MuhSelectedItem = derp;