【问题标题】:WindowsStore ComboBox SelectedIndex not being properly updated?WindowsStore ComboBox SelectedIndex 未正确更新?
【发布时间】:2015-08-01 03:58:35
【问题描述】:

我有一个绑定到我的 ViewModel 的 ComboBox。 SelectedIndex 绑定到 ViewModel 上的属性。

我想要做的是,在某些情况下,索引上的某些选择变为无效,因此当用户尝试选择它时,它应该显示 错误消息 和 不改变当前选中的项目。

在后端,一切都很好。但是,在 UI 上,ComboBox 的 SelectedIndex 仍然会发生变化。错误消息正确显示,但组合框中的“显示”选定项目不是正确的(例如,组合框当前为“项目 4”,用户选择无效项目“项目 3”,显示错误,但组合框仍显示'第 3 项')。

这里是 XAML 代码供参考:

<ComboBox x:Name="ComboBox_Cover"
                      HorizontalAlignment="Stretch"
                      ItemsSource="{Binding Path=Covers}"
                      SelectedIndex="{Binding Path=Cover,
                                              Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                      Style="{StaticResource Style_ComboBox_CheckSelector}" />

还有我的 ViewModel:

private int _Cover = 0;
    public int Cover
    {
        get { return _Cover; }
        set
        {
            bool canChangeCover = true;

            if(IfInvalid())
            {
                canChangeCover = false;
                ShowCoversError();

                RaisePropertyChanged("Cover");
            }

            if(canChangeCover)
            {
                _Cover = value;
                RaisePropertyChanged("Cover");
            }
        }
    }

我做错了吗?

我发现的当前解决方法是使用 OnSelectionChanged 事件并在此处将 SelectedIndex 设置为适当的值(如果无效)。虽然我不确定这是否是一个好的解决方法。

谢谢!

【问题讨论】:

  • 你一开始就不应该那样做。如果存在“无效项”,则将其从 ComboBox 中删除。不要将它呈现给用户,只是为了稍后告诉他们他们无论如何都无法选择它。
  • 对不起,我应该更清楚。 “无效项目”是动态发生的。最初,所有项目都已加载。例如,如果用户选择“第 4 项”,则第 3 项及以下的项不应再选择,但其他所有内容仍然可用。如果用户更改为“第 6 项”,则 5 及以下不应再选择。

标签: wpf xaml mvvm combobox windows-store-apps


【解决方案1】:

最简单的做法是利用ComboBoxItemIsEnabled 属性。只需修改ItemsSource 绑定以指向ComboBoxItem 的列表。

C#:

public class MainPageViewModel : INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        Covers = new List<ComboBoxItem>
        {
            new ComboBoxItem { Content = "Item 1", IsEnabled = true },
            new ComboBoxItem { Content = "Item 2", IsEnabled = true },
            new ComboBoxItem { Content = "Item 3", IsEnabled = true },
            new ComboBoxItem { Content = "Item 4", IsEnabled = true }
        };
    }

    public List<ComboBoxItem> Covers { get; set; }

    private int selectedIndex;

    public int SelectedIndex
    {
        get { return selectedIndex; }
        set
        {
            if (SelectedIndex != value)
            {
                foreach (var cover in Covers)
                {
                    if (Covers.IndexOf(cover) < value)
                    {
                        cover.IsEnabled = false;
                    }
                }

                selectedIndex = value;
                NotifyPropertyChanged("SelectedIndex");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

XAML:

<ComboBox 
    HorizontalAlignment="Center" 
    VerticalAlignment="Center" 
    ItemsSource="{Binding Covers}" 
    SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}" />

如果您想在 C# 中保留数据模型的集合,您可以实现 IValueConverter 以将 Cover 列表投影到 ComboBoxItem 列表中。如果您需要将更多值绑定到控件模板,您还可以创建一个继承自 ComboBoxItem 的新类并添加一些额外的依赖属性。例如,我玩弄了这个:

public class CoverComboBoxItem : ComboBoxItem
{
    public string Description
    {
        get { return (string)GetValue(DescriptionProperty); }
        set
        {
            SetValue(DescriptionProperty, value);
            this.Content = value;
        }
    }

    public static readonly DependencyProperty DescriptionProperty =
        DependencyProperty.Register("Description", typeof(string), typeof(CoverComboBoxItem), new PropertyMetadata(""));
}

值得注意的是,为了保持良好的关注点分离,我通常更喜欢将模型属性直接绑定到ComboBoxItemIsEnabled 属性。不幸的是,要完成这项工作,您需要在ComboBox.ItemContainerStyle 中设置绑定。不幸的是,不支持在那里声明绑定。我见过一些变通方法,但实施它们的复杂性远远超过我上面描述的解决方案。

希望有帮助!

【讨论】:

    猜你喜欢
    • 2012-06-18
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    相关资源
    最近更新 更多