SelectedItem未在ComboBox中显示

时间:2016-06-01 18:08:34

标签: wpf mvvm combobox

我在使用C#的WPF应用程序中使用MVVM,并且在正确绑定ComboBox时遇到了问题。

这是我在XAML中的ComboBox行:

<ComboBox ItemsSource="{Binding Repository.Models}" SelectedValue="{Binding Repository.SelectedModel}" DisplayMemberPath="Name"></ComboBox>

这是我的存储库中有趣的部分:

 class Repository : INotifyPropertyChanged
    {
        //init MVVM pattern
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private ObservableCollection<Model> _models;
        public ObservableCollection<Model> Models
        {
            get
            {
                return _models;
            }

            set
            {
                _models = value;
                NotifyPropertyChanged("Models");
            }
        }

        private Model _selectedModel;
        public Model SelectedModel
        {
            get
            {
                return _selectedModel;
            }

            set
            {
                _selectedModel = value;
                NotifyPropertyChanged("SelectedModel");
            }
        }  

这是我的Model类中有趣的部分:

 abstract class Model : INotifyPropertyChanged
    {
        //init MVVM pattern
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string _name;
        public string Name
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

因此,当我选择/更改组合框的不同项时,绑定到Repository.SelectedModel.Parameters的DataGrid会按照我的要求进行更新。 因为我知道,绑定确实有效!

当我重新启动应用程序并调试到我的存储库时,我看到有一个SelectedModel(在启动时反序列化),但ComboBox保持空白。但DataGrid确实显示了正确的数据。

所以绑定本身确实有效,但是对ComboBoxLabel的绑定在某种程度上失败了。

我尝试了很多事情,比如在SelectedItem和SelectedValue之间切换,在Binding和Binding Path之间,在IsSynchronizedWithCurrentItem之间切换为true和false,但到目前为止没有任何工作。

你知道我的错吗? 提前谢谢!

修改 这是我的MainWindowViewModel的有趣部分:

class MainWindowViewModel : INotifyPropertyChanged
    {
        //init MVVM pattern
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private Repository _repository;
        public Repository Repository
        {
            get
            {
                return _repository;
            }

            set
            {
                _repository = value;
                NotifyPropertyChanged("Repository");
            }
        }

这是我的App.xaml.cs,我在其中初始化我的DataContext:

   //init point of app
    public partial class App : Application
    {
        private MainWindowViewModel mainWindowViewModel;

        //gets fired as the app starts
        protected override void OnStartup(StartupEventArgs e)
        {
            //create the ViewModel
            mainWindowViewModel = new MainWindowViewModel();

            //create the mainWindow
            var mainWindow = new MainWindow();        
            mainWindow.DataContext = mainWindowViewModel;

            //show the mainWindow
            mainWindow.Show();
        }

2 个答案:

答案 0 :(得分:1)

在ComboBox中尝试SelectedItem而不是SelectedValue。

答案 1 :(得分:1)

  

当我重新启动应用程序并调试到我的存储库时,我发现有一个SelectedModel (在启动时反序列化)但是ComboBox保持空白。但DataGrid确实显示了正确的数据。

看起来反序列化就是问题所在。

您有一个反序列化的所选项目。这意味着创建了一个新的Model实例,其中包含Name的任何内容,Properties即可。并且您在Model中有一个ObservableCollection<Model>个实例列表,这些实例显示在ComboBox中。

您向我们保证,至少有时,ComboBox.SelectedItem绑定SelectedModel,但由于某些原因,您问题中的代码会绑定ComboBox.SelectedValue。那不行。以下是ComboBox.SelectedValue的使用方式:

<ComboBox
    ItemsSource="{Binding Repository.Models}" 
    SelectedValuePath="Name"
    SelectedValue="{Binding SelectedModelName}"
    />

...您必须在viewmodel上拥有String SelectedModelName { get; set; }属性。当选择更改时,Name将为Model的{​​{1}}属性分配该属性。但是你没有ComboBox,而你却不想要它,所以忘掉SelectedModelName

返回SelectedValueSelectedItem从绑定中获取ComboBox的值,并尝试在其Items列表中找到该确切对象。由于确切对象不在该列表中,因此它不会选择任何内容。 SelectedModel中的某个项可能具有相同的名称且具有相同的Repository.Models,但它与Properties的实际实例不同。 Model并未查找ComboBox中值相同的双胞胎;它寻找相同的对象。

SelectedItem适用于SelectedModel.Properties,因为DataGrid不知道或不关心DataGrid中的内容。你给它一个集合,这很好。

所以:如果你想反序列化Models并让它具有任何意义,你需要做的是继续反序列化,但然后找到等价物 SelectedModel中的项目(相同Repository.Models,相同Name),并将该实际对象实例分配给Properties

您可能想要超载SelectedModel不要的。我这样做是为了解决同样的问题。在C#中不会产生最终的行为,并且会在你最不期望的时候咬你,因为你无形中改变了框架代码中发生的行为。我花了几天时间跟踪我创建的那些错误,我再也不会对自己这么做了。

相关问题