Binding to Command dall'esterno di un UserControl
-
06-07-2019 - |
Domanda
Ho un semplice UserControl contenente Label, ComboBox e Button. In breve, deve essere utilizzato in quasi tutte le mie viste molte volte, ogni volta fornito con diversi ItemsSource e CreateItemCommand usando i collegamenti alle mie proprietà ViewModel.
Label e ComboBox fanno parte di un altro UserControl (LabeledComboBox) che funziona perfettamente.
Il problema è che quando provo a associare un comando in una finestra che contiene il mio UserControl ottengo la seguente eccezione:
Non è possibile impostare un 'Binding' sulla proprietà 'CreateItemCommand' di tipo 'MutableComboBox'. Un "Binding" può essere impostato solo su DependencyProperty di DependencyObject.
Ecco XAML per 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>
Ecco il codebehind per questo:
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
}
Come puoi vedere, utilizzo due approcci diversi per la registrazione dei miei DP: ItemsSource è preso da ItemsControl DP e CreateItemCommand è creato da DependencyProperty.Register (...). Ho provato a usare Button.CommandProperty.AddOwner (...) ma ho avuto la stessa eccezione.
Ecco come provo a legare:
<Window ...
xmlns:uc="clr-namespace:Albo.Presentation.Templates">
<uc:MutableComboBox Label="Combo"
ItemsSource="{Binding Path=Recipients}"
CreateItemCommand="{Binding Path=CreateNewRecipient}"/>
</Window>
Il DataContext della finestra è impostato su ViewModel appropriato che fornisce un oggetto ObservableCollection di destinatari e un ICommand CreateNewRecipient come proprietà semplici.
Cosa sto facendo di sbagliato? L'unica cosa che voglio in questo caso particolare è esporre una proprietà Button.Command da usare al di fuori del mio UserControl, proprio come ItemsSource. Sto cercando di usare i comandi nel modo sbagliato? Come posso associare i comandi dei miei controlli utente da altri controlli o finestre?
Considerami un principiante con questa roba Command and DependencyProperty. Qualsiasi aiuto sarebbe apprezzato. Ho cercato su Google tutta la notte e non ho trovato nulla utilizzabile nel mio caso. Perdonate il mio inglese.
Soluzione
Hai registrato il nome sbagliato per la tua proprietà di dipendenza. Dovrebbe essere:
public static readonly DependencyProperty CreateItemCommandProperty =
DependencyProperty.Register(
"CreateItemCommand",
typeof(ICommand),
typeof(MutableComboBox)
);
Nota che la stringa è " CreateItemCommand " ;. È necessario leggere questa documentazione MSDN per informazioni dettagliate sulle convenzioni per proprietà di dipendenza.