【问题标题】:Reset combobox selected item on set using MVVM使用 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(),它应该可以工作

标签: c# wpf mvvm combobox selecteditem


【解决方案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 同步的一种优雅方式。例如,在这种情况下,您希望在选择绑定期间重置选择。

这里的一个问题是为什么我们必须首先更新选择。那是因为SelectedItemSelectedValue 是分开分配的,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 问题的仅链接答案。相反,投票/标记以关闭为重复,或者,如果问题不是重复的,定制此特定问题的答案。
    猜你喜欢
    • 2013-05-29
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-04
    • 1970-01-01
    相关资源
    最近更新 更多