从对象设置ComboBox的SelectedItem

时间:2016-04-21 15:46:43

标签: c# wpf entity-framework mvvm combobox

我在Visual Studio 2015中使用提供数据的Entity Framework 6(EF)构建MVVM Light WPF应用程序。我有一个ComboBox,显示了有人需要接受药物测试的原因,它看起来像这样:

<ComboBox ItemsSource="{Binding ReasonsForTest}"
    SelectedItem="{Binding Path=ReasonsForTestVm,
                     UpdateSourceTrigger=PropertyChanged}"
    DisplayMemberPath="Description" />

ReasonsForTest属于ReasonForTestViewModel类:

public class ReasonForTestViewModel: ViewModelBase
{
    private int _ReasonForTestId;
    private string _ReasonForTestAbbr;
    private string _description;

    public int ReasonForTestId
    {
        get { return _ReasonForTestId; }
        set
        {
            if (value == _ReasonForTestId) return;
            _ReasonForTestId = value;
            RaisePropertyChanged();
        }
    }

    public string ReasonForTestAbbr
    {
        get { return _ReasonForTestAbbr; }
        set
        {
            if (value == _ReasonForTestAbbr) return;
            _ReasonForTestAbbr = value;
            RaisePropertyChanged();
        }
    }

    public string Description
    {
        get { return _description; }
        set
        {
            if (value == _description) return;
            _description = value;
            RaisePropertyChanged();
        }
    }
}

我有一个数据服务类,其中包含以下代码,用于获取ComboBox的有效值的数据:

public async Task<ObservableCollection<ReasonForTestViewModel>> GetReasonsForTest()
{
    using (var context = new MyEntities())
    {
        var query = new ObservableCollection<ReasonForTestViewModel>
            (from rt in context.ReasonForTests
             orderby rt.description
             select new ReasonForTestViewModel
             {
                 ReasonForTestId = rt.ReasonForTestID,
                 ReasonForTestAbbr = rt.ReasonForTestAbbr,
                 Description = rt.description,
             });
        return await Task.Run(() => query);
    }
}

视图模型使用以下内容填充ComboBox

var dataService = new TestDataService();    
ReasonsForTest = await dataService.GetReasonsForTest();

ComboBox具有正确的数据;但是,当应用程序启动时,它没有选择正确的值 - 它在加载时显示为空白。 SelectedItemReasonsForTestVm)也属于该类型ReasonForTestViewModel,并从数据库中填充此人的一个项目。我已逐步完成了代码,以确保ReasonsForTestVm拥有正确的数据,而且确实如此。

这是ReasonsForTestVm的属性:

public ReasonForTestViewModel ReasonForTestVm
{
    get
    {
        return _reasonForTestVm;
    }

    set
    {
        if (Equals(value, _reasonForTestVm)) return;
        _reasonForTestVm = value;
        RaisePropertyChanged();
    }
}

我在这里做错了什么?我快要忘记了!

更新:抱歉,上面的媒体资料名称令人困惑。固定的。

1 个答案:

答案 0 :(得分:2)

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

将集合绑定到ItemsSource时,UI中会显示这些项目的表示形式。每个表示都绑定到绑定到SelectedItem的集合中找到的实例。例如,如果您使用DataTemplate来创建该表示,那么您将在每个中找到DataContext将是该集合中的其中一个实例。

当您选择其中一个表示时,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;} } 属性现在保存绑定到该表示的集合中的实例。

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

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

<ComboBox ItemsSource="{Binding MuhItems}"
          SelectedItem="{Binding MuhSelectedItem}" />

绑定到

muhViewModel.MuhSelectedItem = new Item(2);

如果您尝试以这种方式手动更新所选项目......

ItemsSource

用户界面将更改。选择器看到ItemsSource已更改,是的,但它在SelectedItem集合中找不到该实例。它不知道具有值2的Item的一个实例等同于具有相同值的任何其他Item。所以它什么都不做。 (对于真正发生的事情来说,这有点过于简单。你可以破坏JustDecompile并亲眼看看。在那里真正令人费解。)

在这种情况下,您应该做的是使用绑定到ItemsSource的集合中找到的实例更新var derp = muhViewModel.MuhItems.FirstOrDefault(x => x.MuhValue == 2); muhViewModel.MuhSelectedItem = derp; 。在我们的例子中,

luaopen_*

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