Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用MVVM重置集合上的组合框选定项_C#_Wpf_Mvvm_Combobox_Selecteditem - Fatal编程技术网

C# 使用MVVM重置集合上的组合框选定项

C# 使用MVVM重置集合上的组合框选定项,c#,wpf,mvvm,combobox,selecteditem,C#,Wpf,Mvvm,Combobox,Selecteditem,我在WPF应用程序中使用一个组合框,并遵循MVVM。有一个字符串列表,我想显示在我的组合框中 XAML: 现在,当我执行这段代码并且SomeCondition(value)返回false时,SelectedItem返回旧的字符串值,但在我的视图中,ComboBox中的selected item是我选择的值。让我们假设我的组合框中显示了10个字符串的集合。除第二个和第四个元素外,所有值都良好(第二个和第四个值的SomeCondition返回false)。如果选择第二个或第四个元素selectedI

我在WPF应用程序中使用一个组合框,并遵循MVVM。有一个字符串列表,我想显示在我的组合框中

XAML:


现在,当我执行这段代码并且SomeCondition(value)返回false时,SelectedItem返回旧的字符串值,但在我的视图中,ComboBox中的selected item是我选择的值。让我们假设我的组合框中显示了10个字符串的集合。除第二个和第四个元素外,所有值都良好(第二个和第四个值的SomeCondition返回false)。如果选择第二个或第四个元素selectedItem,则所需的内容不会更改。但是我的代码没有正确地完成这项工作。如果我选择了第二个图元,则视图仍将第二个图元显示为选定图元。我知道我的代码有问题。但是它是什么?

尝试将XAML更改为

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

这是一个非常有趣的问题。首先,我同意其他人的观点,这是一种不推荐的处理无效选择的方法。正如@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
,这样就不必先赋值

如果您正在寻找一个MVVM/XAML可重用的解决方案,那么我将其放在一起作为另一个线程。这使用了WPF行为,并且管理起来非常简单。没有外部LIB。在溶液中复制

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedIndex="{Binding currSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} " />

我知道这有点晚了,但从WPF 4.5开始,您可以像这样使用Delay命令:

    <ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged}" />


这让我在前几天花了好几个小时查找资料后省了不少钱。对于其他可能有效或可能无效的方法,您可以阅读帖子及其评论。

这不是一个非常用户友好的设计。如果我在组合框中选择某个项目,我希望它是我选择的项目。您应该从组合框中删除无效选项。如果选择的有效性基于另一个UI元素的选定值,则更改该选择将触发重新生成组合框的ItemSource。这是显示所有项目的要求,无法更改。我同意不要显示无效选项,或将其灰显并禁用对其的选择,这就是UI的用途。在视图中选择第二项,但显示IDataErrorInfo错误。因此,您可以从setter中删除“验证”,并将其放入IDataErrorInfo中。但是,如果您将最后一个“good”值设置为selecteditem,并执行OnPropertyChanged()“Mode=TwoWay”,那么它应该可以工作。这是必需的吗?我试图在视图模型构造函数中设置默认值,但效果很好。但是在setter中设置它是失败的。@FaisalHafeez是的,因为您正在更改View和ViewModel中的属性。我们遇到了完全相同的问题,您的解决方法也可以工作。我们还希望显示所有项目,尽管无法选择一个。我们不想禁用控件,因为它只是一个很短的时间段,不可能选择其他项。有没有办法编写一个行为来确保选择器UI元素始终显示正确的属性值?对我来说,这会导致最初选择的值出现轻微的“闪烁”,但效果足够好。我也非常欣赏这个解决方案。似乎正确的答案是让框架将“value”设置为已传递,然后将其重置为原始值。但是,有人可以解释为什么OP的解决方案不起作用(在通知之前进行测试和分配)。请不要发布其他堆栈溢出问题的链接答案。取而代之的是,投票/标记为重复结束,或者,如果问题不是重复的,则定制此特定问题的答案。谢谢!!因为这个问题,我搜索了好几个小时,延迟解决了我想要的问题!
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);
    }
}
<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedIndex="{Binding currSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} " />
{
    set{ 
        currSelection = -1;
    }
}
    <ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=1, UpdateSourceTrigger=PropertyChanged}" />