WPF MVVMcomboboxSelectedItem或SelectedValue无法正常工作

更新

经过一番调查。 什么似乎是问题是SelectedValue / SelectedItem发生在项目源完成加载之前。 如果我坐在一个rest点,等待几秒钟,按预期工作。 不知道我怎么去解决这个问题。

结束更新

我有一个应用程序在WPF中使用MVVM与ComboBox。 以下是ViewModel示例。 我遇到的问题是当我们离开我们的页面并迁移回ComboBox不select当前选定的值。

查看模型

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; } } } 

为了这个例子,让我们说MyObject有两个属性(文本和Id)。 我的combobox的XAML看起来像这样。

XAML

 <ComboBox Name="MyComboBox" Height="23" Width="auto" SelectedItem="{Binding Path=SelectedObject,Mode=TwoWay}" ItemsSource="{Binding Objects}" DisplayMemberPath="Text" SelectedValuePath="Id"> 

无论采用哪种方式,当我回到页面并重新组装对象时,ComboBox将不会select该值。 该对象通过get属性返回正确的对象。

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

你有没有尝试在viewmodel中实现INotifyPropertyChanged ,然后在SelectedItem被设置时引发PropertyChanged事件?

如果这本身并没有解决这个问题,那么您将能够在浏览页面时手动引发PropertyChanged事件,这应该足以让WPF自己重绘并显示正确的选定项目。

设置IsSynchronizedWithCurrentItem="True"为我工作!

您需要在SelectedItem属性之前放置ItemsSource属性。 前几天我遇到一个博客提到这个问题。

我有类似的问题,并确保我正确实施IEquatable解决了。 当绑定发生时,它试图看看对象是否匹配,所以确保你正确地实现你的相等性检查。

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

一个可能的解决scheme是

根据select的项目标识,恢复项目源集合上的对象,并将其设置为所选项目属性。

例:

 <ctrls:ComboBoxControlBase SelectedItem="{Binding Path=SelectedProfile, Mode=TwoWay}" ItemsSource="{Binding Path=Profiles, Mode=OneWay}" IsEditable="False" DisplayMemberPath="Name" /> 

绑定到ItemSource的Property是:

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

绑定到SelectedItem的属性是:

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

恢复代码是:

  [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"); } } } } 

我希望它可以帮助你。 我花了很多时间寻找答案,但是我找不到。

当离开当前页面时,与ComboBoxItemsSource属性关联的CollectionView被清除。 而且由于ComboBox IsSyncronizedWithCurrent属性默认为true,所以SelectedItemSelectedValue属性被重置。
这似乎是绑定中的内部数据types问题。 正如其他人上面所build议的那样,如果使用SelectedValue而不是通过绑定视图模型上的int属性,它将起作用。 对于你来说快捷方式是重写MyObject上的Equals运算符,以便在比较两个MyObjects时比较实际的Id属性。

另一个提示:如果你重组你的视图模型并使用SelectedValue ,只有在SelectedValuePath=Id其中Idint时才使用它。 如果使用string键,则绑定到ComboBoxText属性而不是SelectedValue

我之前也注意到了这种行为。 我注意到SelectedIndex属性不会导致相同的错误。 如果你可以重构你的ViewModel来显示选定的项目的索引,并绑定到那个,你应该很好去。

我有同样的问题。 事情是。 选定的项目不知道它应该从集合中使用哪个对象。 所以你必须说select的项目使用集合中的项目。

 public MyObject SelectedObject { get { Objects.find(x => x.id == _selectedObject.id) return _selectedObject; } set { _selectedObject = value; } } 

我希望这有帮助。

我有一个非常简单的回答这个问题。 首先将下面的代码添加到View IsSynchronizedWithCurrentItem =“True”。

接下来,当您在ViewModel中分配一个新的对象时,该对象将被保存到该属性而不是私有成员。

Viewmodel Proptery应该看起来像这样

  public Role SelectedObject { get { return object; } set { if (value != null) { if (!object.Equals(value)) { object = value; OnPropertyChanged(() => SelectedObject ); } } } } 

这应该解决这个问题。

我在这个问题上争取了一段时间。 在我的情况下,我使用复杂types(List)作为项目源,并使用KeyType作为选定的值。 在加载事件中,KeyType被设置为null。 这使一切都打破。 当密钥更改时,所有子元素都不会更新。 事实certificate,当我添加一个检查,以确保KeyType的build议值不为空,一切按预期工作。

  #region Property: SelectedKey // s.Append(string.Format("SelectedKey : {0} " + Environment.NewLine, SelectedKey.ToString())); private KeyType _SelectedKey = new KeyType(); public KeyType SelectedKey { get { return _SelectedKey; } set { if(value != null ) if (!_SelectedKey.Equals(value)) { _SelectedKey = value; OnPropertyChanged("SelectedKey"); } } } #endregion SelectedKey 

SelectedValuePathSelectedValue的types必须完全相同。

例如,如果SelectedValuePath的types是Int16并且绑定到SelectedValue的属性的types是int则它将不起作用。

我花了好几个小时才find这个问题,这就是为什么我问了这么多问题之后,我在这里回答。 也许像我这样的另一个可怜的家伙有同样的问题可以看到它。

我遇到了一个显示颜色列表(List <Brush>)的ComboBox的问题。
select颜色是可能的,但是当selectclosures时不显示(尽pipe属性被改变了!)

此修复程序覆盖了 ComboBox(刷子)中所选types的Equals(object obj)方法 ,因为Brush是密封的,所以这很简单。 所以我写了一个EqualityBrush类,其中包含一个Brush并实现Equals:

 public class EqualityBrush { public SolidColorBrush Brush { get; set; } public override bool Equals(object o) { if (o is EqualityBrush) { SolidColorBrush b = ((EqualityBrush)o).Brush; return b.Color.R == this.Brush.Color.R && b.Color.G == this.Brush.Color.G && b.Color.B == this.Brush.Color.B; } else return false; } } 

使用我的新的EqualityBrush类而不是正常的刷类的列表修复了问题!

我的Combobox XAML看起来像这样:

 <ComboBox ItemsSource="{Binding BuerkertBrushes}" SelectedItem="{Binding Brush, Mode=TwoWay}" Width="40"> <ComboBox.Resources> <DataTemplate DataType="{x:Type tree:EqualityBrush}"> <Rectangle Width="20" Height="12" Fill="{Binding Brush}"/> </DataTemplate> </ComboBox.Resources> </ComboBox> 

请记住, ViewModel中的“Brush”属性现在必须是Type EqualityBrush!

这可能是你应用DataContext到页面的方式。 在WPF中,每当你导航到一个页面,一切都会被重新初始化,构造函数被调用,加载的方法,一切。 所以如果你在你的View中设置你的DataContext,你无疑会吹走用户select的SelectedItem。 为了避免使用您的网页的KeepAlive财产。

 <Page KeepAlive="True" ...> ... </Page> 

这将导致在返回到已经访问过的页面时,只会触发Loaded事件。 所以你需要确保你在初始化时设置DataContext(在外部或在构造函数中)而不是Load。

但是,这只适用于该页面的实例。 如果您导航到该页面的新实例,则会再次调用构造函数。

ComboBox.SelectionBoxItem.ToString()

IsSyncronizedWithCurrent = False将使其工作。

使用加载事件:

 private void cmb_Loaded(object sender, RoutedEventArgs e) { if (cmb.Items.Count > 0) cmb.SelectedIndex = 0; } 

这个对我有用。

我通过在UserControl_Loaded事件中添加调度程序来解决问题

  Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { combobox.SelectedIndex = 0; }));