MVVM 集合的ViewModel

来源:互联网 发布:看不见的客人 知乎 编辑:程序博客网 时间:2024/04/29 18:40

下面分享一个自己在工作中实际用到的关于集合处理的ViewModel。
    我们都知道,WPF中,有关于Combobox、List以及DataGrid等等的控件,其属性DataSource基本上都会与ObservableCollection<T>绑定。下面给出一个我自己的解决方案,以供参考。
    主要实现的功能有:提供数据源、双击、选项改变、添加数据项、移除数据项等

UML
 接口    ICollectionViewModel<T>

属性:
接口中的PageViewModel是分页的实现,此篇不分析和提供该类的实现方式!

Collection是对外提供的集合类
DoubleClickCommand是当双击选项时触发的命令
SelectedIndex是选中的索引
SelectedItem是选中的项
SelectedIsNull表示选中项是否为空

方法:
Add(T item)表示向集合中添加项
Clear():表示清空集合
GetIndex(Func<T, bool> predicate):表示根据条件获取该项在集合中所在的索引值
GetItem(Func<T, bool> predicate):根据条件获取项
Remove(T item):移除某项
RemoveAt(int index):移除指定索引项

事件:
CollectionChanged:参考ObservableCollection<T>中的CollectionChanged
DoubleClick:双击命令触发的事件
SelectedCheanged:选中项发生改变


 实现类  CollectionViewModel




实现代码:
   接口实现代码

/// <summary>    /// Collection ViewModel Interface.    /// </summary>    /// <typeparam name="T">    /// </typeparam>    public interface ICollectionViewModel<T>    {        /// <summary>        /// 选中项发生改变.        /// </summary>        event EventHandler SelectedChanged;        /// <summary>        /// 双击项        /// </summary>        event EventHandler DoubleClick;        /// <summary>        /// 集合改变.        /// </summary>        event NotifyCollectionChangedEventHandler CollectionChanged;        /// <summary>        /// 双击命令.        /// </summary>        ICommand DoubleClickCommand { get; }        /// <summary>        /// 数据源.        /// </summary>        ReadOnlyObservableCollection<T> Collection { get; }        /// <summary>        /// 选中项.        /// </summary>        T SelectedItem { get; set; }        /// <summary>        /// 选中项索引.        /// </summary>        int SelectedIndex { get; set; }        /// <summary>        /// 选中项是否为空.        /// </summary>        bool SelectedIsNull { get; }        /// <summary>        /// 根据条件获取索引.        /// </summary>        /// <param name="predicate">        /// The predicate.        /// </param>        /// <returns>        /// The <see cref="int"/>.        /// </returns>        int GetIndex(Func<T, bool> predicate);        /// <summary>        /// 根据条件获取项.        /// </summary>        /// <param name="predicate">        /// The predicate.        /// </param>        /// <returns>        /// The <see cref="T"/>.        /// </returns>        T GetItem(Func<T, bool> predicate);        /// <summary>        /// 添加项.        /// </summary>        /// <param name="item">        /// The item.        /// </param>        void Add(T item);        /// <summary>        /// 清空集合.        /// </summary>        void Clear();        /// <summary>        /// 移除项.        /// </summary>        /// <param name="item">        /// The item.        /// </param>        void Remove(T item);        /// <summary>        /// 移除制定索引项.        /// </summary>        /// <param name="index">        /// The index.        /// </param>        void RemoveAt(int index);        /// <summary>        /// 转换为List.        /// </summary>        /// <returns>        /// The <see>        /// <cref>IList</cref>        /// </see>        /// .        /// </returns>        IList<T> ToList();    }

    

    类实现代码

  
 /// <summary>    /// The Collection ViewModel实现.    /// </summary>    /// <typeparam name="T">    /// <tag>泛型</tag>    /// </typeparam>    public class CollectionViewModel<T> : ViewModelBase, ICollectionViewModel<T>    {        /// <summary>        /// The seletected item.        /// </summary>        private T seletectedItem;        /// <summary>        /// The selected index.        /// </summary>        private int selectedIndex;        /// <summary>        /// Initializes a new instance of the <see cref="CollectionViewModel{T}"/> class.        /// </summary>        public CollectionViewModel()        {            this.DoubleClickCommand = new RelayCommand(                () =>            {                if (DoubleClick != null)                {                    DoubleClick(this, new EventArgs());                }            });            this.ListCollection = new ObservableCollection<T>();            this.Collection = new ReadOnlyObservableCollection<T>(this.ListCollection);            this.ListCollection.CollectionChanged += (o, e) => this.OnCollectionChanged(e);        }        /// <summary>        /// The selected changed.        /// </summary>        public event EventHandler SelectedChanged;        /// <summary>        /// The double click.        /// </summary>        public event EventHandler DoubleClick;        /// <summary>        /// The collection changed.        /// </summary>        public event NotifyCollectionChangedEventHandler CollectionChanged;        /// <summary>        /// Gets the double click command.        /// </summary>        public ICommand DoubleClickCommand { get; private set; }        /// <summary>        /// Gets or sets the page view model.        /// </summary>        public IListPageViewModel PageViewModel { get; set; }        /// <summary>        /// Gets a value indicating whether selected is null.        /// </summary>        public bool SelectedIsNull        {            get            {                return null == this.SelectedItem;            }        }        /// <summary>        /// Gets or sets the selected index.        /// </summary>        public int SelectedIndex        {            get            {                return this.selectedIndex;            }            set            {                this.selectedIndex = value;                this.RaisePropertyChanged("SelectedIndex");            }        }        /// <summary>        /// Gets or sets the selected item.        /// </summary>        public T SelectedItem        {            get            {                return this.seletectedItem;            }            set            {                this.seletectedItem = value;                if (!this.SelectedIsNull && this.SelectedChanged != null)                {                    this.SelectedChanged(this, new EventArgs());                }                this.RaisePropertyChanged("SelectedItem");            }        }        /// <summary>        /// Gets the collection.        /// </summary>        public ReadOnlyObservableCollection<T> Collection { get; private set; }        /// <summary>        /// Gets the list collection.        /// </summary>        protected ObservableCollection<T> ListCollection { get; private set; }        /// <summary>        /// The add.        /// </summary>        /// <param name="item">        /// The item.        /// </param>        public void Add(T item)        {            this.ListCollection.Add(item);                   }        /// <summary>        /// The clear.        /// </summary>        public void Clear()        {            this.ListCollection.Clear();        }        /// <summary>        /// The get index.        /// </summary>        /// <param name="predicate">        /// The predicate.        /// </param>        /// <returns>        /// The <see cref="int"/>.        /// </returns>        /// <exception cref="NullReferenceException">        /// </exception>        public int GetIndex(Func<T, bool> predicate)        {            if (predicate == null)            {                throw new NullReferenceException("predicate is null");            }            var index = this.ListCollection.Where(predicate)                .Select(m => this.ListCollection.IndexOf(m))                .SingleOrDefault();            return index;        }        /// <summary>        /// The get item.        /// </summary>        /// <param name="predicate">        /// The predicate.        /// </param>        /// <returns>        /// The <see cref="T"/>.        /// </returns>        /// <exception cref="NullReferenceException">        /// </exception>        public T GetItem(Func<T, bool> predicate)        {            if (predicate == null)            {                throw new NullReferenceException("predicate is null");            }            var obj = this.ListCollection.SingleOrDefault(predicate);            return obj;        }        /// <summary>        /// The remove at.        /// </summary>        /// <param name="index">        /// The index.        /// </param>        public void RemoveAt(int index)        {            this.ListCollection.RemoveAt(index);        }        /// <summary>        /// The to list.        /// </summary>        /// <returns>        /// The <see cref="IList{T}"/>.        /// </returns>        public IList<T> ToList()        {            return this.ListCollection.ToList();        }        /// <summary>        /// The remove.        /// </summary>        /// <param name="item">        /// The item.        /// </param>        public void Remove(T item)        {            this.ListCollection.Remove(item);        }        /// <summary>        /// The on collection changed.        /// </summary>        /// <param name="e">        /// The e.        /// </param>        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)        {            var handler = this.CollectionChanged;            if (handler != null)            {                handler(this, e);            }        }    }





通过实现代码可以看出,CollectionViewModel<T>主要提供了两个集合
 public ReadOnlyObservableCollection<T> Collection { get; private set; }
protected ObservableCollection<T> ListCollection { get; private set; } 

对于Collection,它是对外只读集合,也就是说,所以对集合的操作都必须通过CollectionViewModel类来实现,这样,我们就通过CollectionViewModel控制了集合的修改,防止了外部修改集合。

使用:
    Combobox:

   
<ComboBox      DataContext="{Binding FactoryRegulationCollectionVm, Mode=OneWay}"      ItemsSource="{Binding Collection}"     SelectedItem="{Binding SelectedItem, Mode=TwoWay}"     DisplayMemberPath="FactoryRegulationName" />



    DataGrid:此处的DataGrid提供了双击选项的功能
   
<DataGrid      Grid.Row="2" BorderBrush="#D24726" BorderThickness="1"     DataContext="{Binding ImageinfoCollectionViewModel}"     ItemsSource="{Binding Collection}"                        SelectedItem="{Binding SelectedItem,Mode=TwoWay}"      IsReadOnly="True" CanUserSortColumns="False"           HorizontalAlignment="Center"                    AutoGenerateColumns="False"          >             <i:Interaction.Triggers>                <!--双击事件绑定到命令-->                <i:EventTrigger EventName="PreviewMouseDoubleClick">                    <i:InvokeCommandAction                        Command="{Binding DoubleClickCommand}"></i:InvokeCommandAction>                </i:EventTrigger>            </i:Interaction.Triggers>            <DataGrid.Columns>                <DataGridTextColumn Header="{DynamicResource lang_SerialNumber}" Binding="{Binding rowID}" />            </DataGrid.Columns>        </DataGrid>



未解决的问题:
    1.  多选的问题,就是在DataGrid中,选中多个项,暂时没有想到比较好的解决方案。
    2.  其他未使用到的。上面给出的处理方案都是在实际工作中遇到的,也许还有其他需要解决的,但是暂时还未遇到。


注:
    1.  本人的ViewModel主要依靠的框架是  MVVM Light  ,感兴趣的可以自行百度
    2.  本人 QQ:351157970,  欢迎交流,一起讨论工作中遇到的问题
    3.  Demo代码:CollectionViewModel


0 0
原创粉丝点击