使用 MVVM 重置组合框选定项目
Posted
技术标签:
【中文标题】使用 MVVM 重置组合框选定项目【英文标题】:Reset combobox selected item on set using MVVM 【发布时间】:2013-07-25 03:28:44 【问题描述】:我在我的 WPF 应用程序中使用 ComboBox 并遵循 MVVM。我想在 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,我可以在我的视图中看到它。
现在这就是我想要实现的目标。当我从我的视图中更改所选项目时,我需要检查值是好/坏(或任何东西)设置所选项目,否则不要设置它。所以我的视图模型变成了这样。
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(value) 返回 false 时,SelectedItem 返回旧字符串值,但在我看来,ComboBox 中的选定项是我选择的值。因此,假设我的 ComboBox 中显示了 10 个字符串的集合。除第二个和第四个元素外,所有值都很好(SomeCondition 对第二个和第四个值返回 false)。如果我选择第二个或第四个元素 selectedItem ,我想要什么不要改变。但是我的代码没有正确执行此操作。如果我选择第二个元素,则视图仍将第二个元素显示为选中状态。我知道我的代码有问题。但它是什么?
【问题讨论】:
这不是一个非常用户友好的设计。如果我在组合框中选择某些东西,我希望它是我选择的项目。您应该改为从组合框中删除无效选项。如果选择的有效性基于另一个 UI 元素的选定值,则更改该选择应触发重建组合框的 ItemSource。 这是显示所有项目的要求,不能更改。 我同意不显示无效选项,或者将它们变灰并禁用它们的选择,这就是 UI 的用途。 让您在视图中选择第二个项目,但会显示 IDataErrorInfo 错误。所以你可以从你的设置器中删除你的“验证”并将其放在 IDataErrorInfo 中。但是,如果您将最后一个“好”值设置为您的选定项目并执行 OnPropertyChanged(),它应该可以工作 【参考方案1】:这是一个非常有趣的问题。首先,我同意其他人的观点,即这是处理无效选择的不推荐方法。正如@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);
Dispatcher
是在另一个 UI 同步期间处理一些 UI 同步的一种优雅方式。例如,在这种情况下,您希望在选择绑定期间重置选择。
这里的一个问题是为什么我们必须首先更新选择。那是因为SelectedItem
和SelectedValue
是分开分配的,ComboBox
上显示的内容不依赖于SelectedItem
(可能是SelectedValue
,这里我不确定)。另一个有趣的点是,如果 SelectedValue 发生变化,SelectedItem
必须发生变化,但 SelectedItem
在发生变化时不会更新 SelectedValue
。因此,您可以选择绑定到SelectedValue
,这样您就不必先分配。
【讨论】:
我们遇到了完全相同的问题,您的解决方法有效。我们还想显示所有项目,尽管不可能选择一个。而且我们不想禁用该控件,因为它只是在很短的时间内无法选择另一个项目。有没有办法编写一个行为来确保选择器 UI 元素始终显示正确的属性值? 对我来说,这会导致最初选择的值略有“闪烁”,但效果很好。 我也非常感谢这个解决方案。似乎正确的答案是让框架将“值”设置为传递,然后将其重置为原始值。但是,有人可以解释为什么 OP 的解决方案不起作用(在通知之前进行测试和分配)。【参考方案2】:我知道这有点晚了,但从 WPF 4.5 开始,您可以像这样使用延迟命令:
<ComboBox ItemsSource="Binding ItemsCollection" SelectedItem="Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged" />
这让我在前几天查了几个小时的东西之后救了我。对于其他可能有效或无效的方法,您可以阅读 this 帖子及其 cmets。
【讨论】:
谢谢!!由于这个问题,我搜索了几个小时,延迟解决了,就像我想要的一样! 和卡塔琳娜一样,搜索了几个小时,这很完美,谢谢!!!【参考方案3】:尝试将 XAML 更改为此
<ComboBox ItemsSource="Binding ItemsCollection" SelectedItem="Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" />
【讨论】:
"Mode=TwoWay" 是必需的吗?我试图在我的视图模型构造函数中设置默认值,效果很好。但是在 setter 中设置它是失败的。 @FaisalHafeez 是的,因为您也在更改 View 和 ViewModel 中的属性【参考方案4】:<ComboBox ItemsSource="Binding ItemsCollection" SelectedIndex="Binding currSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged " />
在你的虚拟机中
set
currSelection = -1;
【讨论】:
【参考方案5】:如果您正在寻找 MVVM / XAML 可重用解决方案,我将其放在另一个线程中。这使用 WPF 行为,并且非常易于管理。没有外部库。复制到解决方案中。
ComboBox Selected Item Clear Behavior
【讨论】:
请不要发布对其他 Stack Overflow 问题的仅链接答案。相反,投票/标记以关闭为重复,或者,如果问题不是重复的,定制此特定问题的答案。以上是关于使用 MVVM 重置组合框选定项目的主要内容,如果未能解决你的问题,请参考以下文章