kurgaan
kurgaan

Reputation: 796

WPF UserControl DependencyProperty and INotifyPropertyChanged on an ObservableCollection

In an attempted MVVM implimentation, I have a UserControl implementing INotifyPropertyChanged. OnFilePathsChanged seems to be called after FilePaths has the new value, so it just copies it over again. If I don't implement INotifyPropertyChanged OnPropertyChanged the VIEWMODEL never gets updated. I have read that using INotifyPropertyChanged together with a DependencyProperty is redundant but I can't figure out the best way to do this. What am I missing. Is there a cleaner way to implement a UserControl with a bound ObservableCollection?

UserControl code

private void LoadFileMenuItem_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog();

        if (dialog.ShowDialog() == true)
        {
            FilePaths.Add(dialog.FileName);
            OnPropertyChanged("FilePaths");
        }
    }

 private void InitFilePathsProperty()
    {
        this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(FilePaths_PropertyChanged);
    }

    void FilePaths_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        this.SetValue(FilePathsProperty, ImageFilePaths);
    }

    public static readonly DependencyProperty FilePathsProperty = DependencyProperty.Register("FilePaths", typeof(ObservableCollection<string>), typeof(FileDisplayControl),
                new PropertyMetadata(OnImageFilePathsChanged));

    private static void OnFilePathsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue != null)
        {
            var myFileDisplayControl = obj as FileDisplayControl;
            if (myFileDisplayControl != null &&
                myFileDisplayControl.FilePaths != null)
            {
                FilePaths = this.GetValue(args.Property) as ObservableCollection<string>;
            }
        }
    }

    public ObservableCollection<string> FilePaths
    {
        get { return this.GetValue(FilePathsProperty) as ObservableCollection<string>;  }
        set { this.SetValue(FilePathsProperty, value); }
    }

In the VIEWMODEL

    public ObservableCollection<string> ViewModelFilePaths
    {
        get            {                return _viewModelFilePaths;            }
        set            {                _viewModelFilePaths = value;            }
    }

Upvotes: 0

Views: 833

Answers (1)

Sheridan
Sheridan

Reputation: 69989

It's a bit unclear as to what you're actually asking, but I think that this will help you whatever you're asking. If you have a view model that is data bound to a UserControl.DataContext, you can still data bind to any DependencyPropertys defined in that control using a RelativeSource Binding. Take this example from inside the UserControl:

Binding to the UserControl DependencyProperty:

<ListBox ItemsSource="{Binding FilePaths, RelativeSource={RelativeSource 
    AncestorType={x:Type YourPrefix:YourUserControl}}}" ... />

Binding to the data bound view model property:

<ListBox ItemsSource="{Binding ViewModelFilePaths}" ... />

You should implement the INotifyPropertyChanged interface in the view model, not the UserControl... at least, it is more customary to declare DependencyPropertys in a UserControl. However, if you have declared normal CLR properties that you want to data bind to in the UserControl, then you should implement the INotifyPropertyChanged interface there too.

Upvotes: 1

Related Questions