3

I've a Class say One with following properties

class One
{    
    public int Id {get; set;}
    public string Name {get; set;}
    public string Salary {get; set;}
    public string Designation {get; set;}    
}

Now I created a list of type One like this in a ViewModel

public class OneViewModel
{
    public OneViewModel(){
        lstOne = new List<One>();
    }
    List<One> lstOne {get;set;}
    public int UserId {get;set;} 
}

and added few objects to the list in ActionResult and passed it in model.

public ActionResult Index()
{
    OneViewModel model =  new OneViewModel();
    model.lstOne.Add(new One{Id=1,Name="Sam",Salary="5000", Designation="Manager" });
    model.lstOne.Add(new One{Id=2,Name="Akash",Salary="6000", Designation="Manager" });
    model.lstOne.Add(new One{Id=3,Name="Sid",Salary="7000", Designation="Manager" });

    return View(model);
}

Now when the post method is called I want to find out which objects were deleted or added in lstOne and which properties were changed of a given object in lstOne.

[HttpPost]
public ActionResult Index(OneViewModel model)
{

   //what to do here, any ideas

}

I don't want to use an old approach of iterating through list and comparing objects and properties, is there any other way around. I saw ObservableCollection and NotifyCollectionChangedEventArgs on MSDN site, however, I was not able to get the right approach for implementing it in order to resolve my query.

BWA
  • 5,314
  • 7
  • 29
  • 42
Sid M
  • 4,268
  • 4
  • 27
  • 47
  • Do you just want to know the object is dirty or you need to compare the values ? – Eldho Apr 21 '16 at 11:03
  • You could come up with your own solutions for the *change tracking*. For *Add / Remove* you could override the *List.Add* , *List.Remove* and use some additional properties like *IsNew* , *IsDeleted* whenever these methods are called. Similarly for *Property updates* you could use the *INotifyPropertyChanged* interface and maintain a collection of changed properties at the class *One* level – bit Apr 21 '16 at 11:04
  • NotifyCollectionChangedEventArgs just indicates that an object has changed and doesn't indicate which objects changed. You have to write the code to determine what has changed. See followng webpage : http://stackoverflow.com/questions/1329138/how-to-make-databinding-type-safe-and-support-refactoring/1333874#1333874 – jdweng Apr 21 '16 at 11:10
  • 2
    Between calls the collection does not belong to you. You can not control what was happening to it and how. The only thing you can do to be 100% sure is to compare the old and the new. – BWA Apr 21 '16 at 11:13
  • @BWA : comparison would be the last thing that I'll be doing to accomplish the task. However, I really don't want to do that. Hence looking for other alternatives. – Sid M Apr 21 '16 at 11:18

2 Answers2

0

I'm not sure about this, i didn't implemented anywhere

use ObservableCollection instead of List

In your viewmodel you have something like this.

public class OneViewModel
 {
    public OneViewModel()
    {
     ObservableCollection<One> observableColleciton = new ObservableCollection<One>();
            observableColleciton.CollectionChanged += list_CollectionChanged;
    }

     public bool IsCollecitonDirty { get; set; }

    static void list_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                isCollectionDirty = true;
                break;
            case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                break;
            case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                isCollectionDirty = true;
                break;
            case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                break;
            case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                break;
            default:
                break;
        }
    }
}

At your model you can something similar to this.

class One : INotifyPropertyChanged
{

    private int _id;

    public int Id
    {
        get { return _id; }
        set
        {
            _id = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;


    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            IsModelDirty = true;
            // PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public bool IsModelDirty { get; set; }
}

Use IsCollectionDirty to ensure your collection is changed and to ensure model is good you could try

observableColleciton.Any(g=>g.IsModelDirty)
Eldho
  • 6,426
  • 3
  • 38
  • 66
  • 1
    I doubt this will work in an MVC context with HttpGet and HttpPost methods: the OneViewModel object in the HttpPost method is a new object, populated from the HTTP Form Post by means of Model Binding. There is no 'old' or 'initial' object that will cause these Changed events to be triggered during Model Binding. – Peter B Apr 21 '16 at 11:14
  • I'm not sure this works with Model Binding, In that scenario we could try for custom model binder – Eldho Apr 21 '16 at 11:19
0

Ok, lets analize that.

Ideal situation

  1. Get collection from Index()
  2. Modify or not, and set modification indicators in collection
  3. Put collction into Index(OneViewModel model)

In Index(OneViewModel model) you can analize indicators and do work. Everything works fine.

But word isn't ideal and im bad man and i want to harm your app. Or something goes wrong and client works bad.

Bad situation

  1. Get collection from Index()
  2. Modify or not, and set modification indicators in collection somethig goes wrong and indicators not set.
  3. Put collction into Index(OneViewModel model)

In Index(OneViewModel model) you can analize indicators and you cannot detect changes becouse indicators not set.

Or someone cretes client which uses your collection and he don't know he must set indicators and he don't do that. Or ... many many other situations.

You can rely only on what is 100% sure. In this case as I say in comment, Between calls the collection does not belong to you. You can not control what was happening to it and how.

Only good way is comparision.

BWA
  • 5,314
  • 7
  • 29
  • 42