【问题标题】:SelectedItemIndex Mismatch when using a CollectionView refresh on a SL ComboBox在 SL ComboBox 上使用 CollectionView 刷新时 SelectedItemIndex 不匹配
【发布时间】:2013-08-24 21:23:31
【问题描述】:

如果您有一个绑定到 CollectionView 的 ComboBox。在该 CollectionView 上发出 REFRESH 并过滤掉某些项目,从而更改所选项目的位置并将 Collection 的大小减小到 SelectedItemIndex 以下。然后它使组合框处于不可用状态。从下面的示例中

  • 按下设置选定项的按钮
  • 然后我在 collectionview 上发出刷新
  • 从视觉上看,一切似乎都很棒...因为在 Combobox 中,您将 5 视为所选项目
  • 单击组合框,SL 崩溃并出现恼人的错误

我将它追溯到 ComboBox 中的一个部分,在打开它时它会将 SelectedItemIndex 传递给方法 SetContentPresenter。但是 SelectedItemIndex 是错误的,所以它崩溃了:-(

这是我的视图模型代码

 public class MainPageViewModel : INotifyPropertyChanged
{
    public ObservableCollection<DataObject> ItemSource;
    public ICollectionView CollectionView { get; set; }

    public MainPageViewModel()
    {
        ItemSource = new ObservableCollection<DataObject>();

        var source = new CollectionViewSource();

        for (int i = 0; i < 10; i++ )
        {
            ItemSource.Add(new DataObject(){ Id = i, Description = i.ToString()});
        }

        Filters = new List<string>();
        source.Source = ItemSource;
        CollectionView = source.View;

        CollectionView.Filter = (x) =>
            {
                if (Filters.Count == 0)
                    return true;

                return  Filters.Contains((x as DataObject).Description);
            };

    }

    public event PropertyChangedEventHandler PropertyChanged;

    internal void ButtonPushed()
    {
        SelectedObject = ItemSource.First(x => x.Description == "5");
        Filters.Add("1");            
        Filters.Add("5");
        CollectionView.Refresh();
    }

    public List<string> Filters
    {
        get;
        set;
    }


    DataObject _SelectedObject;
    public DataObject SelectedObject
    {
        get
        {
            return _SelectedObject;
        }
        set
        {
            if (_SelectedObject != value)
            {
                _SelectedObject = value;

                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("SelectedObject"));
            }
        }
    }

型号代码

public class DataObject
{
    public int Id { get; set; }
    public string Description { get; set; }

    public override string ToString()
    {
        return Description;
    }
}

查看代码

<StackPanel x:Name="LayoutRoot" Background="White">
    <ComboBox ItemsSource="{Binding CollectionView}" SelectedItem="{Binding SelectedObject, Mode=TwoWay}"></ComboBox>
    <Button Content="Run Test" Click="Button_Click_1"></Button>
</StackPanel>

代码背后

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        this.DataContext = new MainPageViewModel();
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        var vm = DataContext as MainPageViewModel;


        Dispatcher.BeginInvoke(() =>vm.ButtonPushed());
    }
}

我最终在我的项目中解决了这个问题,方法是不对组合框 selecteditem 进行双向绑定,而是使用 CollectionView 上的 CurrentItem 作为我的 VM 和组合框之间的通信管道。这样,我可以在发出刷新之前将当前项设为空,然后我可以设置当前项,使组合框保持一致状态。

在应用程序中,此组合框是级联组合框实现的一部分。因此,在另一个组合框中选择一个项目会导致另一个组合框被过滤掉,但已经选择的项目可能仍然是一个可行的选项。

【问题讨论】:

  • 感谢,您似乎在 Combobox 控件中发现了一个错误。甚至可能在 Selector 基类中。我想知道它是否也会影响 ListBox 和其他衍生产品。 - 有问题吗,或者这只是一个观察?
  • 酷我在连接上记录了一个错误。因为它是 SL,所以我认为这根本不重要 :-)。我想我只是在审查我没有做一些根本上愚蠢的事情,而且我认为这应该有效而不会使 SL 崩溃是正确的。我找不到其他人遇到这个问题,所以我觉得我缺少一些简单的东西。 connect.microsoft.com/VisualStudio/feedback/details/780938/…

标签: c# .net silverlight combobox silverlight-5.0


【解决方案1】:

问题似乎是您已将绑定的 SelectedItem 设置为特定的数据对象,然后从列表中删除了该对象。我看不到 ComboBox 会做什么,除了抛出一个错误,因为它的状态已经无效。所以我认为这不是 ComboBox 问题。

刷新后我要做的是查看 SelectedObject 是否仍然是有效对象。如果不是,则将其从列表中删除。这样就不会报错了。

 internal void ButtonPushed() {
        SelectedObject = ItemSource.First(x => x.Description == "5");
        Filters.Add("1");
        Filters.Add("5");
        CollectionView.Refresh();
        ValidateSelectedDataObject();
    }

    public void ValidateSelectedDataObject() {
        DataObject currentSelectedItem = this.SelectedObject;
        this.SelectedObject = null;
        foreach (DataObject item in CollectionView) {

            if (item.Id == currentSelectedItem.Id) {
                this.SelectedObject = currentSelectedItem;
            }
        }

    }

格雷格

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-09
    • 2011-10-14
    • 1970-01-01
    • 2013-02-24
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多