代码之家  ›  专栏  ›  技术社区  ›  MGSoto

在这种情况下,如何模拟可观察集合的效果?

  •  2
  • MGSoto  · 技术社区  · 16 年前

    我正在为另一个应用程序制作一个配置编辑器,并使用反射从配置类中提取可编辑字段。下面的类是各种“DataTypeViewModels”的基类,并显示如何获取和设置适当的属性。

    public abstract class DataTypeViewModel<T> : ViewModelBase
    {
        Func<T> getFunction;
    
        Action<T> setAction;
    
        public const string ValuePropertyName = "Value";
    
        public string Label { get; set; }
    
        public T Value
        {
            get
            {
                return getFunction.Invoke();
            }
    
            set
            {
                if (getFunction.Invoke().Equals(value))
                {
                    return;
                }
    
                setAction.Invoke(value);
    
                // Update bindings, no broadcast
                RaisePropertyChanged(ValuePropertyName);
            }
        }
    
         /// <summary>
        /// Initializes a new instance of the StringViewModel class.
        /// </summary>
        public DataTypeViewModel(string sectionName, string label)
        {
            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.
            }
            else
            {
                Label = label;
    
                getFunction = new Func<T>(() =>
                    {
                        return (T)Settings.Instance.GetType().GetProperty(sectionName).PropertyType.
                            GetProperty(label).GetValue(Settings.Instance.GetType().GetProperty(sectionName).GetValue(Settings.Instance, null), null);
                    });
    
                setAction = new Action<T>(value =>
                    {
                        Settings.Instance.GetType().GetProperty(sectionName).PropertyType.GetProperty(label).
                            SetValue(Settings.Instance.GetType().GetProperty(sectionName).GetValue(Settings.Instance, null), value, null);
                    });
            }
        }
    }
    

    这部分按我希望的方式工作,下一部分是字符串列表上的示例DataTypeViewModel。

    public class StringListViewModel : DataTypeViewModel<ICollection<string>>
    {
        /// <summary>
        /// The <see cref="RemoveItemCommand" /> property's name.
        /// </summary>
        public const string RemoveItemCommandPropertyName = "RemoveItemCommand";
    
        private RelayCommand<string> _removeItemCommand = null;
    
        public ObservableCollection<string> ObservableValue { get; set; }
    
        /// <summary>
        /// Gets the RemoveItemCommand property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public RelayCommand<string> RemoveItemCommand
        {
            get
            {
                return _removeItemCommand;
            }
    
            set
            {
                if (_removeItemCommand == value)
                {
                    return;
                }
    
                var oldValue = _removeItemCommand;
                _removeItemCommand = value;
    
                // Update bindings, no broadcast
                RaisePropertyChanged(RemoveItemCommandPropertyName);
            }
        }
    
        /// <summary>
        /// The <see cref="AddItemCommand" /> property's name.
        /// </summary>
        public const string AddItemCommandPropertyName = "AddItemCommand";
    
        private RelayCommand<string> _addItemCommand = null;
    
        /// <summary>
        /// Gets the AddItemCommand property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public RelayCommand<string> AddItemCommand
        {
            get
            {
                return _addItemCommand;
            }
    
            set
            {
                if (_addItemCommand == value)
                {
                    return;
                }
    
                var oldValue = _addItemCommand;
                _addItemCommand = value;
    
                // Update bindings, no broadcast
    
                RaisePropertyChanged(AddItemCommandPropertyName);
            }
        }
    
        /// <summary>
        /// Initializes a new instance of the StringListViewModel class.
        /// </summary>
        public StringListViewModel(string sectionName, string label) : base(sectionName, label)
        {
            ObservableValue = new ObservableCollection<string>(Value);
            AddItemCommand = new RelayCommand<string>(param =>
                {
                    if (param != string.Empty)
                    {
                        Value.Add(param);
                        ObservableValue.Add(param);
                    }
                });
    
            RemoveItemCommand = new RelayCommand<string>(param =>
                {
                    if (param != null)
                    {
                        Value.Remove(param);
                        ObservableValue.Remove(param);
                    }
                });
        }
    }
    

    正如您在构造函数中看到的,我当前将“Value”镜像到一个名为“observeValue”的新observeCollection中,然后由XAML中的ListView绑定到该集合。这样做效果很好,但克隆列表似乎是一种很难做到的方法。在绑定到值的同时,我尝试添加:

    RaisePropertyChanged("Value");
    

    添加到AddItemCommand和removItemCommand,但这不起作用,ListView将不会得到更新。正确的方法是什么?

    1 回复  |  直到 16 年前
        1
  •  2
  •   Aran Mulholland JohnnyAce    16 年前

    INotifyCollectionChanged 它类似于NotifyPropertyChanged,但ObservableCollection使用它来通知插入/删除/重置。。。

      public class MyCustomCollection : INotifyCollectionChanged
        {
            public event NotifyCollectionChangedEventHandler CollectionChanged;
    
            protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                if (CollectionChanged != null)
                {
                    CollectionChanged(this, e);
                }
            }
    
            public void Add(Object o)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, o));
            }
    
            public void Remove(Object o)
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, 0));
            }
    
            public void Clear()
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
    
            public void Move(Object o, Int32 newIndex)
            {
                Int32 oldIndex = 0; // can get the old index position using collection.IndexOf(o);
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move,
                    o, newIndex, oldIndex));
            }
    
            public Object this[Int32 index]
            {
                get
                {
                    return null; // return collection[index];
                }
                set
                {
                    Object oldValue = null;  // get old value using collection[index];
                    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace,
                        value, oldValue));
                }
            }
        }
    

    here