【发布时间】:2015-04-24 20:56:54
【问题描述】:
我已经尽可能地简化了这个问题。基本上我正在覆盖组合框的“null”值。因此,如果选定的项目被删除,它会恢复为“(null)”。不幸的是,这种行为是错误的,我点击了删除,ObservableCollection 项被删除,因此属性绑定被更新并按预期返回“(null)”项。但组合框外观显示为空白。然而它绑定的值是正确的......这个问题可以用下面的代码重现。
要重现此问题,您选择一个项目,然后点击删除。请注意此时调用了以下行(当您删除所选项目时)。所以它是一个断点的好地方。
if (m_Selected == null)
{
return Items[0]; //items 0 is ItemNull
}
还请注意,我已尝试通过强制更新 DisplayMemberPath 的属性来修复它。这不起作用。
MainWindow.xaml
<Window x:Class="WPFCodeDump.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding Selected, Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox>
<Button Click="ButtonBase_OnClick">Remove Selected</Button>
</StackPanel>
</Window>
MainWindowViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace WPFCodeDump
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
//Item class
public class Item : ViewModelBase
{
public Item(string name)
{
m_Name = name;
}
public string Name
{
get { return m_Name; }
}
private string m_Name;
public void ForcePropertyUpdate()
{
OnPropertyChanged("Name");
}
}
//Item class
public class ItemNull : Item
{
public ItemNull()
: base("(null)")
{
}
}
class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
m_Items.Add(new ItemNull());
for (int i = 0; i < 10; i++)
{
m_Items.Add(new Item("TestItem" + i));
}
Selected = null;
}
//Remove selected command
public void RemoveSelected()
{
Items.Remove(Selected);
}
//The item list
private ObservableCollection<Item> m_Items = new ObservableCollection<Item>();
public ObservableCollection<Item> Items
{
get { return m_Items; }
}
//Selected item
private Item m_Selected;
public Item Selected
{
get
{
if (m_Selected == null)
{
return Items[0]; //items 0 is ItemNull
}
return m_Selected;
}
set
{
m_Selected = value;
OnPropertyChanged();
if(m_Selected!=null) m_Selected.ForcePropertyUpdate();
}
}
}
}
MainWindow.xaml.cs
using System.Windows;
namespace WPFCodeDump
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
((MainWindowViewModel) DataContext).RemoveSelected();
}
}
}
结果:
【问题讨论】:
-
return Items[0]... 从什么返回?那应该做什么?当然,您只需要
Selected = Items[0](假设Items[0]是数据绑定集合中的实际项目)。 -
您是否尝试在 SelectedItem-Binding 中设置
UpdateSourceTrigger=PropertyChanged? -
它返回 ItemNull(),它是 m_Items 内部的一个实例
-
@Tomtom 试过了,同样的问题。反正不是默认属性改变了吗?
-
@Sheridan
Selected属性的值是ItemNull的实例,它被添加到VM 构造函数的第一行。在 Snoop 中检查程序可确认SelectedItem正在返回正确的对象实例,但显示的文本仍为空白,而不是应为的字符串"(null)"。