2

My ViewModelBase class is:

public abstract class ViewModelBase:INotifyPropertyChanged, IDisposable, INotifyCollectionChanged
{
    #region Constructor

    protected ViewModelBase()
    {
    }

    #endregion // Constructor
    #region DisplayName

    /// <summary>
    /// Returns the user-friendly name of this object. 
    /// Child classes can set this property to a new value,
    /// or override it to determine the value on-demand.
    /// </summary>
    public virtual string DisplayName { get; protected set; }

    #endregion // DisplayName


    #region Debugging Aides

    /// <summary>
    /// Warns the developer if this object does not have
    /// a public property with the specified name. This 
    /// method does not exist in a Release build.
    /// </summary>
    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real,  
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }
    }

    /// <summary>
    /// Returns whether an exception is thrown, or if a Debug.Fail() is used
    /// when an invalid property name is passed to the VerifyPropertyName method.
    /// The default value is false, but subclasses used by unit tests might 
    /// override this property's getter to return true.
    /// </summary>
    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    #endregion // Debugging Aides
    #region INotifyPropertyChanged Members
    /// <summary>
    /// raised when property of this object has some new value  
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion

    #region IDisposable Members

    public void Dispose()
    {
        this.OnDispose();
    }

    /// <summary>
    /// child classes can override this method to perform cleanup logic,like removing eventhandlers and disposing objects
    /// Anindya
    /// </summary>
    protected virtual void OnDispose()
    {
        //no implementation has been done here 
        //intentionhally I have done so 
        //so that this method will be only used for the overriding of this method
        //by default nothing I have kept in this method
    }

    #endregion

    #region INotifyCollectionChanged Members
    /// <summary>
    /// Occurs when an item is added, removed, changed, moved, or the entire list is refreshed.
    /// </summary>
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent)
    {
        //NotifyCollectionChangedEventHandler handler = this.CollectionChanged;
        //if (handler != null)
        //{
        //    var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction 
        //}
    }

    #endregion

}

and my WorkSpaceViewModel is inheriting from ViewModelBase as followes:

public abstract class WorkspaceViewModel:ViewModelBase
{
    #region Fields

    RelayCommand _closeCommand;


    #endregion // Fields

    #region Constructor

    protected WorkspaceViewModel()
    {
    }

    #endregion // Constructor

    #region CloseCommand

    /// <summary>
    /// Returns the command that, when invoked, attempts 
    /// to remove this workspace from the user interface. 
    /// </summary>
    public ICommand CloseCommand
    {
        get
        {
            if (_closeCommand == null)
                _closeCommand = new RelayCommand(param => this.OnRequestClose());

            return _closeCommand;
        }
    }       

    private void CanDoSomeImportantMethod()
    {
    }
    #endregion // CloseCommand

    #region RequestClose [event]

    /// <summary>
    /// Raised when this workspace should be removed from the UI.
    /// </summary>
    public event EventHandler RequestClose;

    void OnRequestClose()
    {
        EventHandler handler = this.RequestClose;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    #endregion // RequestClose [event]
}

My ViewModel is inheriting from WorkSpaceViewModel as followes:

public class MainWindowViewModel:WorkspaceViewModel,INotifyCollectionChanged
{
    //
    RelayCommand _loadCommand;
    MatchBLL matchBLL = new MatchBLL();
    EfesBetServiceReference.EfesBetClient proxy = new EfesBetClient();
    public MainWindowViewModel()
    {
        _matchObsCollection = new ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC>();
        Load();

        _matchObsCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(_matchObsCollection_CollectionChanged);
    }

    /// <summary>
    /// This will get called when the collection is changed(for reference see http://stackoverflow.com/questions/1427471/observablecollection-not-noticing-when-item-in-it-changes-even-with-inotifyprop)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void _matchObsCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {

    }

    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);
    }
    public ICommand LoadCommand
    {
        get
        {
            if (_loadCommand == null)
            {
                _loadCommand = new RelayCommand(
                    param => this.Load(),
                    param => this.CanLoad
                    );
            }
            return _loadCommand; 
        }
    }

    List<EfesBet.DataContract.GetMatchDetailsDC> matchList;
    ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC> _matchObsCollection;

    public ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC> MatchObsCollection
    {
        get { return _matchObsCollection; }
        set
        {
            _matchObsCollection = value;
            OnPropertyChanged("MatchObsCollection");
        }
    }

    public void Load()
    {
        matchList = new List<GetMatchDetailsDC>();
        matchList = proxy.GetMatch().ToList();
        foreach (EfesBet.DataContract.GetMatchDetailsDC match in matchList)
        {
            _matchObsCollection.Add(match);
        }
        //ajebaje code
        PopulateSahibiKonuk();
    }

    bool CanLoad
    {
        get { return true; }
    }


    #region INotifyCollectionChanged Members

    public event NotifyCollectionChangedEventHandler CollectionChanged;       

    #endregion

Now I am having a DataGrid in UI and I want OnCollectionChanged of my ObservableCollection. How NotifyCollectionChangedAction like add, move, remove, replace, reset my viewmodel should fire. But I do not know how to implement or what I have to do in my base classes or in my viewmodel. Please provide me some useful code or urls or suggestion regarding this.

Thanking you in advance.

DHN
  • 4,807
  • 3
  • 31
  • 45
Anindya
  • 2,616
  • 2
  • 21
  • 25
  • 1
    why don´t you expose/make public the ObserverableCollection directly. So you don´t have to implement the interface INotifyCollectionChanged. Bind your DataGrid to the ObservableCollection so you don´t have to implement the interface on your own. – Jehof Aug 13 '13 at 07:26
  • 1
    Implementing `INotifyCollectionChanged` would only make sense on a view model class that is a collection, i.e. that at least also implements `ICollection`. You would then fire the `CollectionChanged` events in those methods that change the collection, like `Add` or `Remove`. – Clemens Aug 13 '13 at 07:28
  • @Jehof I have a small doubt in my code public ObservableCollection MatchObsCollection { get { return _matchObsCollection; } set { _matchObsCollection = value; OnPropertyChanged("MatchObsCollection"); } } is the OnPropertyChanged("MatchObsCollection"); is correct or wrong? or it should be OnCollectionChanged("MatchObsCollection"); – Anindya Aug 13 '13 at 09:33
  • @AnindyaChatterjee Its correct as it is – Jehof Aug 13 '13 at 09:47

1 Answers1

6

Typically, a view model would not implement the INotifyCollectionChanged interface... that is for collection classes to implement. I have a massive WPF project and I haven't needed to implement that interface once.

I generally use custom collection classes that extend ObservableCollection<T> and these collections already implement the INotifyCollectionChanged interface. Therefore, when I need to display collections, I just add properties for these collections in my view model classes. If I then need to monitor changes in the collection, I would add a handler for the CollectionChanged event.

This is not something that can be built into the base view model unless you are certain that every view model will have a collection of a particular type. Even then, what would you do when you need more than one collection in a view model? You'd have to add a collection property and extra handlers, so why don't you just do that whenever you need to?

Sheridan
  • 68,826
  • 24
  • 143
  • 183