WPF Dependency Property for ItemTemplate Command
I have a custom control that defines the ItemControl and ItemTemplate for this control, i.e.
<ItemsControl Name="ItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Name="SelectionButton" Content="MyButton"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In the code behind, I am specifying a dependency property that allows me to bind the ItemsSource property of the ItemsControl i.e.
public static readonly DependencyProperty ButtonSourceProperty = DependencyProperty.Register(
"ButtonSource", typeof(IEnumerable), typeof(MyControl),
new PropertyMetadata(null, new PropertyChangedCallback(OnButtonSourceChanged)));
public IEnumerable ButtonSource
{
get { return (IEnumerable)GetValue(ButtonSourceProperty); }
set { SetValue(ButtonSourceProperty, value); }
}
private static void OnButtonSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var buttonSelectionControl = (ButtonSelectionControl)d;
buttonSelectionControl.ItemsControl.ItemsSource = (IEnumerable)e.NewValue;
}
public static void SetButtonSource(DependencyObject obj, IEnumerable enumerable)
{
obj.SetValue(ButtonSourceProperty, enumerable);
}
public static IEnumerable GetButtonSource(DependencyObject obj)
{
return (IEnumerable)obj.GetValue(ButtonSourceProperty);
}
so in xaml i can set source for MyControl like this
<local:MyControl ButtonSource={Binding MyCollection} \>
This works, but how can I define a dependency property in MyControl that specifies the command to bind to in MyCollection? I currently have the following declared in xaml for command binding
Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding .}"
How can I abstract this so that I can set the item command to bind in the xaml like:
<local:MyControl ButtonSource={Binding MyCollection}
ButtonCommand={Binding MyCommand} \>
Pointers appreciated.
source to share
Make sure your UserControl has a dependency property for the ICommand, let's say it's called "ButtonCommand".
You may be able to bind to this inside the template for your control:
<ItemsControl Name="ItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Name="SelectionButton" Content="MyButton"
Command="{Binding ButtonCommand, RelativeSource={RelativeSource AncestorType=wpfApplication1:UserControl1}}"
CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Clicking the button should then bring up a set of commands in the "ButtonCommand" dependency property defined in your custom control.
Your ButtonCommand will define (inside your UserControl code):
public static readonly DependencyProperty ButtonCommandProperty = DependencyProperty.Register("ButtonCommand", typeof (ICommand), typeof (UserControl1), new PropertyMetadata(default(ICommand)));
public ICommand ButtonCommand { get { return (ICommand) GetValue(ButtonCommandProperty); } set { SetValue(ButtonCommandProperty, value); }}
Creating a command class that implements ICommand is a template, as you probably know. By putting this in your xaml button:
CommandParameter="{Binding}"
.. it allows you to work with a list item in your command-handling code:
public class TheCommand : ICommand
{
public void Execute(object parameter)
{
var yourListItemObject = parameter as yourListItemObjectType;
}
// boilerplate stuff
public bool CanExecute(object parameter) { return true; }
public event EventHandler CanExecuteChanged;
}
source to share
You can define 2 dependency properties ButtonCommmand
and ButtonCommandParameter
in UserContol.cs file and link them in UserControl xaml like this:
<UserControl x:Class="..."
x:Name="this">
<Button Command="{Binding ButtonCommand, ElementName=this}"
CommandParameter="{Binding ButtonCommandPrameter, ElementName=this}"/>
</UserControl>
source to share