Marks
Marks

Reputation: 3661

Handling DependencyProperty changes in the ViewModel of a UserControl

Im currently trying to get my first WPF Usercontrol to work. It consists of some UI elements and a ViewModel, holding the data and doing the work. It has a List of items as input, and another List of items as output. I need a certain task in my ViewModel to be done, when the list bound to the input changes. But i can't find a way to run a method at change of this List.

I thought the best way is to have 2 DependencyProperties for the input and output list. If the output list changes, the bound objects should be informed as it is registered as DependencyProperty. And i wanted to use the DependencyPropertyChanged delegate to specify the method in my ViewModel to execute on Input change.

public List<AClass> Input
    {
        get { return (List<AClass>)GetValue(InputProperty); }
        set { SetValue(InputProperty, value); }
    }
public static readonly DependencyProperty InputProperty =
        DependencyProperty.Register("Input", typeof(List<AClass>), typeof(MyUserControl), new UIPropertyMetadata(new List<AClass>(),CallBackDelegate));

I tried different approaches to set the delegate in the viewmodel constructor, but they all did not work. How can I specify a method within my viewmodel to execute on change of input List?

Upvotes: 0

Views: 687

Answers (1)

Wonko the Sane
Wonko the Sane

Reputation: 10823

Instead of lists in a DependencyProperty, I would use ObservableCollections. That gives you "automatic" notifications, etc. Here is outta-my-head-probably-not-quite-complete pseudo code to get you started:

ViewModel

using System.Collections.ObjectModel;

namespace MyNamespace;

class MyViewModel
{
    ObservableCollection<AClass> mInput = new ObservableCollection<AClass>();
    ObservableCollection<AClass> mOutput = new ObservableCollection<AClass>();

    public MyViewModel()
    {
        mInput.CollectionChanged += 
            new NotifyCollectionChangedEventHandler(mInput_CollectionChanged);
    }

    void mInput_CollectionChanged(object sender, 
                                  NotifyCollectionChangedEventArgs e)
    {
        DoSomething();    
    }

    public ObservableCollection<AClass> Input
    {
        get { return mInput; }
    }

    public ObservableCollection<AClass> Output
    {
        get { return mOutput; }
    }
}

Somewhere in Control/View

<ItemsControl ItemsSource="{Binding Input}">
    <!-- Rest of control design goes here -->
</ItemsControl>

<ItemsControl ItemsSource="{Binding Output}">
    <!-- Rest of control design goes here -->
</ItemsControl>

Control/View Code-Behind

class MyViewOrControl
{
    // ViewModel member
    private readonly MyViewModel mViewModel = new MyViewModel();

    // Constructor
    public MyViewOrControl()
    {
        InitializeComponent();
        this.DataContext = mViewModel;
    }

    // Property (if needed)
    public ViewModel
    {
        get { return mViewModel; }
    }
}

Upvotes: 1

Related Questions