1
votes

I have the following in my View XAML

<GroupBox Grid.Row="0" Header="Aktionen bei Prüfung Aufbau">
    <ContentControl Content="{Binding BuildUpActions}" ContentTemplate="{StaticResource FullActionListTemplate}" x:Name="BuildUp"/>
</GroupBox>

<GroupBox Grid.Row="1" Header="Aktionen bei Prüfung Abbau">
    <ContentControl Content="{Binding TearDownActions}" ContentTemplate="{StaticResource FullActionListTemplate}" x:Name="TearDown"/>
</GroupBox>

The DataTemplate is defined in a separate resource

<DataTemplate x:Key="FullActionListTemplate">
    <DockPanel LastChildFill="True">
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button Content="Neuer Ausgang" Style="{StaticResource ButtonRowStyle}"
                    Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Path=DataContext.NewFullIOCommand}" 
                    CommandParameter="{Binding **?HOW?**}"
                    />
            <more buttons here...>
        </StackPanel>
        <ContentControl Content="{Binding}" >

        </ContentControl>
    </DockPanel>
</DataTemplate>

The Command is defined in the ViewModel

    public ICommand NewFullIOCommand
    {
        get
        {
            if (this._newFullIOCommand == null)
            {
                this._newFullIOCommand = new Mvvm.RelayCommand(parm => DoNewFullIO(parm));
            } return this._newFullIOCommand;
        }
    }

I want to be able to determine which of the 2 lists generated the Command. I want a CommandParameter to be passed to the command handler which contains the x:Name of the control.

How do I define the binding? Is there a better way?

2
You might want to look at using the TemplateBinding or using a RelativeBinding with a RelativeSource of TemplatedParent. I don't think you can get the x:Name property though, but if you can get back to your content control, then maybe you can use something other property as a sort of "Tag" property.CodingGorilla

2 Answers

5
votes

I took a look at your sample and did a quick edit of the line reading the CommandParameter. After doing this change I inspected this in Snoop (WPF runtime debugger) and saw the CommandParameter being set to the one you described as the desired values to apply.

First off, you can obtain Snoop here:

Snoop

I was able to set the CommandParameter to the name of the enclosing ContentControl by simple doing this:

<DataTemplate x:Key="FullActionListTemplate">
        <DockPanel LastChildFill="True">
            <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right">
                <Button Content="Neuer Ausgang"
                Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Path=DataContext.NewFullIOCommand}" 
                CommandParameter="{Binding Path=Name, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentControl}}}"
                />
            </StackPanel>
            <ContentControl Content="{Binding}" >

            </ContentControl>
        </DockPanel>
    </DataTemplate>

As a side note, your example almost contain a similar technique on the line above, where you bind to the Command property.

0
votes

Create a self-referential property

I hate WPF. But, I just did this: Add this property to your bound datamodel class:

public class MyDataObjectItem
{
    //...
    public MyDataObjectItem Self { get { return this; } }
    //...
}

Then the command parameter is easy:

CommandParameter="{Binding Self}"

Or, apparently this works

CommandParameter="{Binding}"

see https://stackoverflow.com/a/11287478/887092