3
votes

I have a user control that defines an ItemsControl and an ItemTemplate for that control, i.e.,

    <ItemsControl Name="ItemsControl">

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Name="SelectionButton" Content="MyButton"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>

    </ItemsControl>

In the code behind I specify a dependency property that enables 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);
      }

such that in xaml I can set the source for MyControl as follows

<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? Currently I have the following declared in xaml for the command binding

Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
                        CommandParameter="{Binding .}"

How can I abstract this in such a way that I can set the item command to bind to in xaml, something like:

<local:MyControl ButtonSource={Binding MyCollection}
                 ButtonCommand={Binding MyCommand} \>

Pointers appreciated.

2

2 Answers

1
votes

Ensure your UserControl has a dependency property to an ICommand, let's say this is called "ButtonCommand".

You should 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>

The button click should then raise the command set in the "ButtonCommand" dependency property defined in your user control.

Your ButtonCommand would definition (inside the UserControl code) would look like this:

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 which implements ICommand is boilerplate stuff as you probably know. By putting this into your button xaml:

CommandParameter="{Binding}"

..it will allow you to work with the item from the list in the 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;
}
0
votes

You can define 2 dependency properties ButtonCommmand and ButtonCommandParameter in you UserContol's .cs file and bind them in UserControl's xaml like this:

<UserControl x:Class="..."
             x:Name="this">
    <Button Command="{Binding ButtonCommand, ElementName=this}" 
            CommandParameter="{Binding ButtonCommandPrameter, ElementName=this}"/>
</UserControl>