使用 MVVM 重置组合框所选项目

本文关键字:选项 项目 组合 MVVM 使用 | 更新日期: 2023-09-27 18:25:03

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

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.
    }
}

现在这段代码工作正常。我能够从视图中选择,并且可以在视图模型中进行更改,如果我从视图模型中更改选定项,我可以在我的视图中看到它。

现在这就是我想要实现的目标。当我从我的视图中更改所选项目时,我需要检查值是否为好/坏(或任何内容(设置所选项目,否则不要设置它。所以我的观点模型像这样改变。

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 中的选定项是我选择的值。因此,假设我的组合框中显示了 10 个字符串的集合。除第二个和第四个元素外,所有值都很好(SomeCondition 为第 2 个和第 4 个值返回 false(。如果我选择第二个或第四个元素,我希望什么项目不会改变。但是我的代码没有正确执行此操作。如果我选择第二个元素,则视图仍然显示第二个元素为选定。我知道我的代码有问题。但是它是什么?

使用 MVVM 重置组合框所选项目

这是一个非常有趣的问题。首先,我同意其他人的观点,即这是处理无效选择的不推荐方法。正如@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 同步的优雅方法。例如,在本例中,您希望在选择绑定期间重置选择。

这里的一个问题是为什么我们首先必须更新选择。那是因为SelectedItemSelectedValue是单独分配的,ComboBox上的显示内容不取决于SelectedItem(也许SelectedValue,我在这里不确定(。另一个有趣的一点是,如果 SelectedValue 发生变化,SelectedItem必须改变,但SelectedItem在更改时不会更新SelectedValue。因此,您可以选择绑定到SelectedValue这样就不必先分配。

我知道

这有点晚了,但从 WPF 4.5 开始,您可以像这样使用延迟命令:

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

前几天我花了几个小时查找东西,这救了我。对于可能有效或可能无效的其他方法,您可以阅读这篇文章及其评论。

尝试将 XAML 更改为此

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

在您的虚拟机中

{
    set{ 
        currSelection = -1;
    }
}

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

组合框选定项清除行为