WPF MVVM ComboBox SelectedItem或SelectedValue不起作用

cji*_*ibo 40 wpf combobox mvvm

更新

经过一番调查.似乎问题是SelectedValue/SelectedItem在Item源完成加载之前发生.如果我坐在断点并等待几秒钟,它会按预期工作.不知道我将如何解决这个问题.

结束更新

我有一个应用程序在WPF中使用MVVM和ComboBox.下面是ViewModel示例.我遇到的问题是当我们离开页面并迁移回ComboBox时没有选择当前选择的值.

查看模型

public class MyViewModel
{
     private MyObject _selectedObject;
     private Collection<Object2> _objects;
     private IModel _model;

     public MyViewModel(IModel model)
    {
         _model = model;
         _objects = _model.GetObjects();
    }

    public Collection<MyObject> Objects
    {
         get
         {
              return _objects;
         }
         private set
         {
              _objects = value;
         }
     }

     public MyObject SelectedObject
     {
          get
          {
              return _selectedObject;
          }
          set
          {
               _selectedObject = value;
          }
      }
 }
Run Code Online (Sandbox Code Playgroud)

为了这个例子,我们可以说MyObject有两个属性(Text和Id).我的ComboBox XAML看起来像这样.

XAML

<ComboBox Name="MyComboBox" Height="23"  Width="auto" 
    SelectedItem="{Binding Path=SelectedObject,Mode=TwoWay}" 
    ItemsSource="{Binding Objects}"
    DisplayMemberPath="Text"
    SelectedValuePath="Id">
Run Code Online (Sandbox Code Playgroud)

无论我在回到页面时如何配置此对象并重新组装对象,ComboBox都不会选择该值.该对象通过属性中的get返回正确的对象.

我不确定这是否只是ComboBox和MVVM模式工作方式的问题.我们正在进行的文本框绑定正常工作.

小智 31

设置IsSynchronizedWithCurrentItem="True"对我有用!

  • 一直在为此苦苦挣扎。这对我来说非常有效。谢谢 :) (2认同)

Ori*_*rds 27

您是否尝试INotifyPropertyChanged在viewmodel中实现,然后在设置PropertyChanged时引发事件SelectedItem

如果这本身不能解决问题,那么PropertyChanged当您导航回页面时,您将能够自己手动提升事件,这应该足以让WPF重绘自己并显示正确的选定项目.


小智 21

您需要将ItemsSource属性置于SelectedItem属性之前.几天前我偶然发现了一个博客,提到了这个问题.


小智 11

我有类似的问题,它通过确保我正确实现IEquatable解决了.当绑定发生时,它正在尝试查看对象是否匹配,因此请确保您正确实现了相等性检查.


小智 10

在这种情况下,selecteditem绑定不起作用,因为对象的哈希id不同.

一种可能的解决方案是

根据选定的项目ID,恢复itemsource集合上的对象,并将选定的项目属性设置为.

例:

<ctrls:ComboBoxControlBase SelectedItem="{Binding Path=SelectedProfile, Mode=TwoWay}" ItemsSource="{Binding Path=Profiles, Mode=OneWay}" IsEditable="False" DisplayMemberPath="Name" />
Run Code Online (Sandbox Code Playgroud)

绑定到ItemSource的属性是:

public ObservableCollection<Profile> Profiles
{
   get { return this.profiles; }
   private set { profiles = value; RaisePropertyChanged("Profiles"); }
}
Run Code Online (Sandbox Code Playgroud)

绑定到SelectedItem的属性是:

public Profile SelectedProfile 
{
    get { return selectedProfile; }
    set
    {
        if (this.SelectedUser != null)
        {
            this.SelectedUser.Profile = value; 
            RaisePropertyChanged("SelectedProfile");  
        } 
    } 
}
Run Code Online (Sandbox Code Playgroud)

恢复代码是:

    [Command("SelectionChanged")]
    public void SelectionChanged(User selectedUser)
    {
        if (selectedUser != null)
        {
            if (selectedUser is User)
            {
                if (selectedUser.Profile != null)
                {
                    this.SelectedUser = selectedUser;
                    this.selectedProfile = this.Profiles.Where(p => p.Id == this.SelectedUser.Profile.Id).FirstOrDefault();
                    MessageBroker.Instance.NotifyColleagues("ShowItemDetails"); 
                }
            }
        }            
    }
Run Code Online (Sandbox Code Playgroud)

我希望它对你有所帮助.我花了很多时间寻找答案,但我找不到.