问题描述
我在我的WPF应用程序和下面的MVVM使用ComboBox。有一个字符串列表,我想显示在我的ComboBox。
I am using a ComboBox in my WPF application and following MVVM. There is a list of strings which I want to show in my ComboBox.
XAML:
<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" />
查看模型:
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.
}
}
现在这个代码工作正常了。我可以从视图中选择,我可以在ViewModel中获得更改,如果我从我的ViewModel中更改SelectedItem,我可以在我的视图中看到它。
Now this code is working absolutely fine. I am able to select from view and I can get changes in ViewModel and if I change SelectedItem from my ViewModel I can see it in my view.
现在这里是什么我试图实现。当我从我的视图更改所选项目时,我需要检查该值是好/坏(或任何)设置所选项目,否则不设置它。所以我的视图模型变成这样。
Now here is what I am trying to achieve. When I change selected item from my view I need to put a check that value is good/bad (or anything) set selected item else do not set it. So my view model changes like to this.
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.
}
}
现在当我执行这段代码和SomeCondition返回false,SelectedItem返回旧的字符串值,但在我的视图中,ComboBox中的所选项是我选择的值。所以让我假设我有10个字符串的集合显示在我的ComboBox。除了第二和第四个元素(SomeCondition对于第二和第四个值返回false),所有值都是好的。我想要的,如果我选择第二或第四个元素selectedItem不更改。但我的代码没有这样做正确。如果我选择第二个元素,那么视图仍然显示第二个元素为选择。我知道我的代码有什么问题。但是是什么呢?
Now when I execute this code and SomeCondition(value) returns false, SelectedItem returns old string value, but in my view selected item in ComboBox is the the value which I selected. So lets assume I have collection of 10 strings showing in my ComboBox. All values are good except second and fourth element (SomeCondition returns false for 2nd and 4th value). What I want that if I select 2nd or 4th element selectedItem do not change. But my code is not doing this properly. If I select 2nd element then view still displays 2nd element as selected. I know there is something wrong in my code. But what is it?
推荐答案
这是一个非常有趣的问题。首先我同意其他人,这是一个不推荐的方法来处理无效选择。如@blindmeis建议, IDataErrorInfo
是解决它的好方法之一。
This is a very interesting question. First I agree with other guys that this is a not recommended approach to handle invalid selection. As @blindmeis suggests, IDataErrorInfo
is one of good way to solve it.
回到问题本身。满足@Faisal Hafeez想要的解决方案是:
Back to the question itself. A solution satisfying what @Faisal Hafeez wants is:
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);
}
}
Dispatcher
是在另一个UI同步期间处理某些UI同步的一种优雅方式。例如,在这种情况下,您要在选择绑定期间重置选择。
Dispatcher
is an elegant way to handle some UI synchronization during another UI sync. For example in this case, you want to reset selection during a selection binding.
这里的问题是为什么我们必须首先更新选择。这是因为 SelectedItem
和 SelectedValue
分别分配,并且 ComboBox
不依赖于 SelectedItem
(也许 SelectedValue
,我不知道这里)。另一个有趣的点是如果SelectedValue改变, SelectedItem
必须改变,但 SelectedItem
不更新 SelectedValue
时更改。因此,您可以选择绑定到 SelectedValue
,以便您不必先分配。
A question here is why we have to update selection anyway at first. That's because SelectedItem
and SelectedValue
are separately assigned and what display on ComboBox
does not depend on SelectedItem
(maybe SelectedValue
, I am not sure here). And another interesting point is if SelectedValue changes, SelectedItem
must change but SelectedItem
does not update SelectedValue
when it changes. Therefore, you can choose to bind to SelectedValue
so that you do not have to assign first.
这篇关于使用MVVM重置组合框所选项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!