Привязка к команде извне UserControl

У меня есть простой UserControl, содержащий Label, ComboBox и Button. Короче говоря, его нужно использовать почти во всех моих представлениях много раз, каждый раз предоставляя разные ItemsSource и CreateItemCommand, используя привязки к моим свойствам ViewModel.

Label и ComboBox являются частью другого UserControl (LabeledComboBox), который отлично работает.

Проблема в том, что когда я пытаюсь связать команду в окне, содержащем мой UserControl, я получаю следующее исключение:

«Привязка» не может быть установлена ​​для свойства «CreateItemCommand» типа «MutableComboBox». «Привязка» может быть установлена ​​только для свойства DependencyProperty объекта DependencyObject.

Вот XAML для MutableComboBox:

<UserControl x:Class="Albo.Presentation.Templates.MutableComboBox"
x:Name="MCB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:uc="clr-namespace:Albo.Presentation.Templates" >
<StackPanel Height="25" Orientation="Horizontal">
    <uc:LabeledComboBox x:Name="ComboBoxControl"
        Label = "{Binding ElementName=MCB, Path=Label}"
        ItemsSource="{Binding ElementName=MCB, Path=ItemsSource}"
        SelectedItem="{Binding ElementName=MCB, Path=SelectedItem}" />
    <Button x:Name="CreateItemButton"
        Grid.Column="1" Width="25" Margin="2,0,0,0"
        Content="+" FontFamily="Courier" FontSize="18" 
        VerticalContentAlignment="Center"
        Command="{Binding ElementName=MCB, Path=CreateItemCommand}"/>
</StackPanel>
</UserControl>

Вот код для него:

public partial class MutableComboBox : UserControl
{
    public MutableComboBox()
    {
        InitializeComponent();
    }

    public string Label
    {
        get { return this.ComboBoxControl.Label; }
        set { this.ComboBoxControl.Label = value; }
    }

    #region ItemsSource dependency property
    public static readonly DependencyProperty ItemsSourceProperty =
        ItemsControl.ItemsSourceProperty.AddOwner(
            typeof(MutableComboBox),
            new PropertyMetadata(MutableComboBox.ItemsSourcePropertyChangedCallback)
        );

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static void ItemsSourcePropertyChangedCallback(
        DependencyObject controlInstance,
        DependencyPropertyChangedEventArgs e)
    {
        MutableComboBox myInstance = (MutableComboBox)controlInstance;

        myInstance.ComboBoxControl.ItemsSource = (IEnumerable)e.NewValue;
    } 
    #endregion // ItemsSource dependency property

    #region SelectedItem dependency property
    // It has just the same logic as ItemsSource DP.
    #endregion SelectedItem dependency property

    #region CreateItemCommand dependency property

    public static readonly DependencyProperty CreateItemCommandProperty =
        DependencyProperty.Register(
            "MutableComboBoxCreateItemCommandProperty",
            typeof(ICommand),
            typeof(MutableComboBox)
        );

    public ICommand CreateItemCommand
    {
        get { return (ICommand)GetValue(CreateItemCommandProperty); }
        set { SetValue(CreateItemCommandProperty,value); }
    }

    #endregion // CreateItem dependency property
}

Как видите, я использую два разных подхода к регистрации своих DP: ItemsSource берется из ItemsControl DP, а CreateItemCommand создается DependencyProperty.Register(...). Я пытался использовать Button.CommandProperty.AddOwner(...), но имел такое же исключение.

Вот как я пытаюсь связать:

<Window ...
    xmlns:uc="clr-namespace:Albo.Presentation.Templates">
    <uc:MutableComboBox Label="Combo" 
        ItemsSource="{Binding Path=Recipients}"
        CreateItemCommand="{Binding Path=CreateNewRecipient}"/>
</Window>

Для DataContext окна задана соответствующая ViewModel, которая предоставляет ObservableCollection of Recipients и ICommand CreateNewRecipient в качестве простых свойств.

Что я делаю неправильно? Единственное, что я хочу в этом конкретном случае, — это предоставить свойство Button.Command для использования за пределами моего UserControl, точно так же, как ItemsSource. Я пытаюсь использовать команды неправильно? Как я могу привязываться к командам моих пользовательских элементов управления из других элементов управления или окон?

Считайте меня новичком в этой работе с Command и DependencyProperty. Любая помощь будет оценена по достоинству. Гуглил всю ночь и не нашел ничего полезного в моем случае. Простите мой английский.


person dvn    schedule 31.07.2009    source источник


Ответы (1)


Вы зарегистрировали неправильное имя для свойства зависимостей. Должен быть:

public static readonly DependencyProperty CreateItemCommandProperty =
        DependencyProperty.Register(
            "CreateItemCommand",
            typeof(ICommand),
            typeof(MutableComboBox)
        );

Обратите внимание на строку «CreateItemCommand». Для получения подробной информации о соглашениях для свойства зависимости.

person Kent Boogaart    schedule 31.07.2009
comment
Спасибо! Вот оно. Предположим, мне нужно больше узнать о том, как это работает. Единственное, что я знал, это то, что оно должно быть уникальным в пределах пространства имен. Итак, каковы критерии имени в DependencyProperty.Register()? Просто удалить слово Property из имени в объявлении или что-то еще? - person dvn; 31.07.2009
comment
Без проблем. Я добавил ссылку на свой ответ, которая должна помочь вам понять это. - person Kent Boogaart; 31.07.2009
comment
Ссылка больше недоступна. - person eYe; 18.04.2016