Reputation: 796
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
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 DependencyProperty
s 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 DependencyProperty
s 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