MVVM binding to a User Control with an ObservableC

2019-08-10 12:51发布

问题:

I have designed a user control with an ObservableCollection dependency property and would like it to be consumed by a MVVM light application. If I set the property in the consuming view's code behind, it works like a charm, but not so when I attempt to use xaml binding as intended with a view-model.

In the control's code-behind I define the dependency property:

/// <summary>
/// The <see cref="ItemsSource" /> dependency property's name.
/// </summary>
public const string ItemsSourcePropertyName = "ItemsSource";

/// <summary>
/// Gets or sets the value of the <see cref="ItemsSource" />
/// property. This is a dependency property.
/// </summary>
public List<string> ItemsSource
{
    get
    {
        return (List<string>)GetValue(ItemsSourceProperty);
    }
    set
    {
        SetValue(ItemsSourceProperty, value);
    }
}

/// <summary>
/// Identifies the <see cref="ItemsSource" /> dependency property.
/// </summary>
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
    ItemsSourcePropertyName,
    typeof(List<string>),
    typeof(ListEditor), new PropertyMetadata(new List<string>(), OnItemsSourcePropertyChanged));

private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ListEditor listEditor = d as ListEditor;
    while (listEditor._stackPanel.Children.Count > 1)
    {
        listEditor._stackPanel.Children.RemoveRange(0, listEditor._stackPanel.Children.Count - 2);
    }

    List<string> newCollection = e.NewValue as List<string>;

    foreach (string item in newCollection)
    {
        ListItemEditor newItem = new ListItemEditor();
        newItem.Text = item;
        newItem.RemoveItem += listEditor.listItemEditor_RemoveItem;

        listEditor._stackPanel.Children.Insert(listEditor._stackPanel.Children.Count - 1, newItem);
    }
} 

In the view I bind the control:

<ucl:ListEditor ItemsSource="{Binding PartNumbers}"/>

In the view model I define the property:

/// <summary>
/// The <see cref="PartNumbers" /> property's name.
/// </summary>
public const string PartNumbersPropertyName = "PartNumbers";

private ObservableCollection<string> _partNumbers = new ObservableCollection<string>();

/// <summary>
/// Sets and gets the PartNumbers property.
/// Changes to that property's value raise the PropertyChanged event. 
/// </summary>
public ObservableCollection<string> PartNumbers
{
    get
    {
        return _partNumbers;
    }

    set
    {
        if (_partNumbers == value)
        {
            return;
        }

        RaisePropertyChanging(PartNumbersPropertyName);
        _partNumbers = value;
        RaisePropertyChanged(PartNumbersPropertyName);
    }
}

What can I do to facilitate the binding effectively?