Home > Blockchain >  How to bind commands to dynamically added buttons?
How to bind commands to dynamically added buttons?

Time:10-14

How can I bind a delegate command to a dynamically added UserControl button?

I have my UserControl button

<ItemsControl
    ItemsSource="{Binding SomeCollection}"
    HorizontalAlignment="Center">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid
                Columns="2" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <DMX_ControlLibrary:DMX_ItemBox
                Width="250"
                Height="150"
                FontSize="12"
                Command="{Binding ItemBoxButtonCommand}"
                Content="{Binding Path=.}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

And in my view model, I have this

private ICommand itemBoxButtonCommand;
public ICommand ItemBoxButtonCommand
{
    get { return (this.itemBoxButtonCommand) ?? (this.itemBoxButtonCommand = new DelegateCommand(ItemButton_Click)); }
}

private void ItemButton_Click()
{
    MessageBox.Show("");
}

Binding doesn't seem to work this way unlike it does on statically added controls. How can I make it work?

CodePudding user response:

As you stated in the comments for ItemBoxButtonCommand:

It's in the viewmodel that contains SomeCollection!

When the data template is applied for each item in the SomeCollection, each DMX_ItemBox will get its DataContext set the the corresponding item, not the data context of the ItemsControl which contains the SomeCollection.

In order to bind to the ItemBoxButtonCommand, you can use a RelativeSource binding to the DataContext of the ItemsControl (which is a parent of the items).

<ItemsControl.ItemTemplate>
   <DataTemplate>
      <DMX_ControlLibrary:DMX_ItemBox
         Width="250"
         Height="150"
         FontSize="12"
         Command="{Binding DataContext.ItemBoxButtonCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
         Content="{Binding Path=.}" />
   </DataTemplate>
</ItemsControl.ItemTemplate>

Alternatively, assign an x:Name to the ItemControl and refer to it with ElementName.

<ItemsControl
   x:Name="MyItemsControl"
   ItemsSource="{Binding SomeCollection}"
   HorizontalAlignment="Center">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
         <UniformGrid
            Columns="2" />
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <DMX_ControlLibrary:DMX_ItemBox
            Width="250"
            Height="150"
            FontSize="12"
            Command="{Binding DataContext.ItemBoxButtonCommand, ElementName=MyItemsControl}"
            Content="{Binding Path=.}" />
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>
  • Related