【问题标题】:finding selected items in Telerik RadGridView using MVVM pattern使用 MVVM 模式在 Telerik RadGridView 中查找选定项目
【发布时间】:2011-09-25 10:10:42
【问题描述】:

我在我的应用程序中使用 Telerik RadGridView,它有一个 GridViewSelectColumn 项目,它允许我选择网格中的各种项目。我有一个操作此选择的按钮,但不确定如何获取所选项目的列表。问题是我在 Caliburn.Micro 中使用了 MVVM 模式。是否需要在视图中找到控件并遍历选中项列表?对于一个简单的任务来说,这似乎需要做很多工作。我会很感激任何想法。

【问题讨论】:

    标签: mvvm telerik selecteditem caliburn.micro radgridview


    【解决方案1】:

    将布尔 IsSelected 添加到集合中的项目:

     public class Customer
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public bool IsSelected { get; set; }
        }
    
     private BindableCollection<Customer> _customers;
            public BindableCollection<Customer> Customers
            {
                get { return _customers; }
                set
                {
                    _customers = value;
                    NotifyOfPropertyChange(() => Customers);
                }
            }
    

    sample code - bitbucket

    download

    【讨论】:

    • 我知道已经有一段时间了,但我正在努力让它发挥作用。请您显示 XAML,因为我似乎无法使绑定工作。或者,您是否可以在无需通过 bitbucket 的情况下将源作为下载提供,因为我无法在那里获得它。
    • @Dave 添加了 repo 的下载
    • 谢谢德里克。我似乎误会了什么。我看到您在 Customer 上有一个 IsSelected 属性,但我在 XAML 中找不到与它的绑定。
    • @Dave 我相信 Telerik 控制和自动生成的列正在处理这个问题。 bool prop IsSelected 将显示为复选框。
    【解决方案2】:

    有一种情况,你不能添加布尔值(例如 ObseravbleCollection。

    请看this解决方案。

    【讨论】:

    • 有人把那篇博文弄好了吗?我试了一下,RadGridView 似乎甚至没有 SelectedItems 属性...
    【解决方案3】:

    Telerik 的 RadGridView 的问题在于,它的 SelectedItem 集合是只读的,因此您不能将双向绑定到 SelectedItems。

    解决方法是使用自定义行为在 RadGridView 和您的 ViewModels SelectedItem 集合之间进行同步

    你可以使用这个行为:

    // Behavior for synchronizing a RadDataGrid's SelectedItems collection with a SelectedItems collection of the ViewModel (the Network)
    // The problem is, that RadDataGrid.SelectedItems is a read-only collection and therefore cannot be used for two-way binding.
    
    class SelectedSyncBehavior
        : Behavior<RadGridView>
    {
        bool _collectionChangedSuspended = false;
    
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged;
        }
    
        /// <summary>
        /// Getter/Setter for DependencyProperty, bound to the DataContext's SelectedItems ObservableCollection
        /// </summary>
        public INotifyCollectionChanged SelectedItems
        {
            get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }
    
        /// <summary>
        /// Dependency Property "SelectedItems" is target of binding to DataContext's SelectedItems
        /// </summary>
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(SelectedSyncBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
    
        /// <summary>
        /// PropertyChanged handler for DependencyProperty "SelectedItems"
        /// </summary>
        private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {
            INotifyCollectionChanged collection = args.NewValue as INotifyCollectionChanged;
            if (collection != null)
            {
                // Hook to the Network's SelectedItems
                collection.CollectionChanged += (target as SelectedSyncBehavior).ContextSelectedItems_CollectionChanged;
            }
        }
    
        /// <summary>
        /// Will be called, when the Network's SelectedItems collection changes
        /// </summary>
        void ContextSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_collectionChangedSuspended) return;    // Don't react recursively to CollectionChanged events
    
            _collectionChangedSuspended = true;
    
            // Select and unselect items in the grid
            if (e.NewItems != null)
                foreach (object item in e.NewItems)
                    AssociatedObject.SelectedItems.Add(item);
    
            if (e.OldItems != null)
                foreach (object item in e.OldItems)
                    AssociatedObject.SelectedItems.Remove(item);
    
            _collectionChangedSuspended = false;
        }
    
        /// <summary>
        /// Will be called when the GridView's SelectedItems collection changes
        /// </summary>
        void GridSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_collectionChangedSuspended) return;    // Don't react recursively to CollectionChanged events
    
            _collectionChangedSuspended = true;
    
            // Select and unselect items in the DataContext
            if (e.NewItems != null)
                foreach (object item in e.NewItems)
                    (SelectedItems as IList).Add(item);
    
            if (e.OldItems != null)
                foreach (object item in e.OldItems)
                    (SelectedItems as IList).Remove(item);
    
            _collectionChangedSuspended = false;
        }
    
    }
    

    将此行为与 RadGridView 一起使用,如下所示:

    <i:Interaction.Behaviors>
       <behaviors:SelectedSyncBehavior SelectedItems="{Binding ViewModel.SelectedItems}" />
    </i:Interaction.Behaviors>
    

    【讨论】:

    • 这应该是选择的答案! Telerik 的博客似乎都缺乏这里找到的完整解决方案。
    • 别忘了实例化 SelectedItems 属性绑定的集合,浪费了 15 分钟...
    【解决方案4】:

    这是@Knasterbax 类的清理副本,带有显式私有修饰符和空传播:

    // Behavior for synchronizing Telerik RadDataGrid's SelectedItems collection 
    //  with a SelectedItems collection of the ViewModel.   
    public class SelectedSyncBehavior : Behavior<RadGridView>
    {
        private bool collectionChangedSuspended;
        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems",
            typeof(INotifyCollectionChanged), typeof(SelectedSyncBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
    
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged;
        }
    
        public INotifyCollectionChanged SelectedItems
        {
            get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }
    
        private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {
            var collection = args.NewValue as INotifyCollectionChanged;
            if (collection == null) return;
            var selectedSyncBehavior = target as SelectedSyncBehavior;
            if (selectedSyncBehavior != null) collection.CollectionChanged += selectedSyncBehavior.ContextSelectedItems_CollectionChanged;
        }
    
        private void ContextSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (collectionChangedSuspended) return;    // Don't react recursively to CollectionChanged events
    
            collectionChangedSuspended = true;
    
            if (e.NewItems != null)
                foreach (var item in e.NewItems)
                    AssociatedObject.SelectedItems.Add(item);
    
            if (e.OldItems != null)
                foreach (var item in e.OldItems)
                    AssociatedObject.SelectedItems.Remove(item);
    
            collectionChangedSuspended = false;
        }
    
        private void GridSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (collectionChangedSuspended) return;    // Don't react recursively to CollectionChanged events
    
            collectionChangedSuspended = true;
    
            if (e.NewItems != null)
                foreach (var item in e.NewItems)
                {
                    var list = SelectedItems as IList;
                    list?.Add(item);
                }
    
            if (e.OldItems != null)
                foreach (var item in e.OldItems)
                {
                    var list = SelectedItems as IList;
                    list?.Remove(item);
                }
    
            collectionChangedSuspended = false;
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      这是上述答案的清理版本。这将删除下划线、添加限定符、访问器、大括号等。

      public class SelectedItemsBehavior : Behavior<RadGridView>
      {
          private bool collectionChangedSuspended;
      
          /// <summary>
          /// Called after the behavior is attached to an AssociatedObject.
          /// </summary>
          /// <remarks>
          /// Override this to hook up functionality to the AssociatedObject.
          /// </remarks>
          protected override void OnAttached()
          {
              base.OnAttached();
              this.AssociatedObject.SelectedItems.CollectionChanged += this.GridSelectedItemsCollectionChanged;
          }
      
          /// <summary>
          /// Getter/Setter for DependencyProperty, bound to the DataContext's SelectedItems ObservableCollection
          /// </summary>
          public INotifyCollectionChanged SelectedItems
          {
              get => (INotifyCollectionChanged)this.GetValue(SelectedItemsProperty);
              set => this.SetValue(SelectedItemsProperty, value);
          }
      
          /// <summary>
          /// Dependency Property "SelectedItems" is target of binding to DataContext's SelectedItems
          /// </summary>
          public static readonly DependencyProperty SelectedItemsProperty =
              DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(SelectedItemsBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
      
          /// <summary>
          /// PropertyChanged handler for DependencyProperty "SelectedItems"
          /// </summary>
          private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
          {
              INotifyCollectionChanged collection = args.NewValue as INotifyCollectionChanged;
              if (collection != null)
              {
                  collection.CollectionChanged += ((SelectedItemsBehavior)target).ContextSelectedItemsCollectionChanged;
              }
          }
      
          /// <summary>
          /// Will be called, when the Network's SelectedItems collection changes
          /// </summary>
          private void ContextSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
          {
              if (this.collectionChangedSuspended)
              {
                  return; 
              }
      
              this.collectionChangedSuspended = true;
      
              if (e.NewItems != null)
              {
                  foreach (object item in e.NewItems)
                  {
                      this.AssociatedObject.SelectedItems.Add(item);
                  }
              }
      
              if (e.OldItems != null)
              {
                  foreach (object item in e.OldItems)
                  {
                      this.AssociatedObject.SelectedItems.Remove(item);
                  }
              }
      
              this.collectionChangedSuspended = false;
          }
      
          /// <summary>
          /// Will be called when the GridView's SelectedItems collection changes
          /// </summary>
          private void GridSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
          {
              if (this.collectionChangedSuspended)
              {
                  return;
              }
      
              this.collectionChangedSuspended = true;
      
              if (e.NewItems != null)
              {
                  foreach (object item in e.NewItems)
                  {
                      ((IList)this.SelectedItems).Add(item);
                  }
              }
      
              if (e.OldItems != null)
              {
                  foreach (object item in e.OldItems)
                  {
                      ((IList)this.SelectedItems).Remove(item);
                  }
              }
      
              this.collectionChangedSuspended = false;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-20
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 2011-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多