fhn*_*eer 9 c# wpf combobox selecteditem mvvm
我在我的WPF应用程序中使用ComboBox并跟随MVVM.我想在ComboBox中显示一个字符串列表.
XAML:
<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" />
Run Code Online (Sandbox Code Playgroud)
查看型号:
public Collection<string> ItemsCollection; // Suppose this has 10 values.
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
Trigger Notify of property changed.
}
}
Run Code Online (Sandbox Code Playgroud)
现在这段代码工作得很好.我可以从视图中进行选择,我可以在ViewModel中进行更改,如果我从ViewModel更改SelectedItem,我可以在我的视图中看到它.
现在这就是我想要实现的目标.当我从我的视图中更改所选项目时,我需要检查值是好/坏(或任何)设置所选项目,否则不设置它.所以我的视图模型就像这样改变了.
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (SomeCondition(value))
_selectedItem = value; // Update selected item.
else
_selectedItem = _selectedItem; // Do not update selected item.
Trigger Notify of property changed.
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我执行此代码并且SomeCondition(value)返回false时,SelectedItem返回旧的字符串值,但在我的视图中,ComboBox中的选定项是我选择的值.所以我假设我的ComboBox中有10个字符串的集合.除第二和第四个元素外,所有值都很好(SomeCondition对第二个和第四个值返回false).我想要的是,如果我选择第二或第四个元素selectedItem不会改变.但是我的代码没有正确地执行此操作.如果我选择第二个元素,则视图仍然显示第二个元素为选中.我知道我的代码有问题.但它是什么?
小智 19
这是一个非常有趣的问题.首先,我同意其他人的意见,这是一种不推荐的处理无效选择的方法.正如@blindmeis所说,IDataErrorInfo
是解决问题的好方法之一.
回到问题本身.满足@Faisal Hafeez想要的解决方案是:
public string SelectedItem
{
get { return _selectedItem; }
set
{
var oldItem=_selectedItem;
_selectedItem=value;
OnPropertyChanged("SelectedItem")
if (!SomeCondition(value)) //If does not satisfy condition, set item back to old item
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => SelectedItem = oldItem),
DispatcherPriority.ApplicationIdle);
}
}
Run Code Online (Sandbox Code Playgroud)
Dispatcher
是在另一个UI同步期间处理某些UI同步的优雅方式.例如,在这种情况下,您希望在选择绑定期间重置选择.
这里的一个问题是为什么我们必须首先更新选择.这是因为SelectedItem
并且SelectedValue
是单独分配的,显示的内容ComboBox
不依赖于SelectedItem
(也许SelectedValue
,我不确定).另一个有趣的观点是,如果SelectedValue发生更改,则SelectedItem
必须更改但更改时SelectedItem
不会更新SelectedValue
.因此,您可以选择绑定,SelectedValue
这样就不必先进行分配.
小智 10
我知道这有点晚了,但从 WPF 4.5 开始,您可以像这样使用 Delay 命令:
<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged}" />
Run Code Online (Sandbox Code Playgroud)
这让我在前几天查了几个小时的东西后救了我。对于其他可能有效也可能无效的方法,您可以阅读这篇文章及其评论。