Search code examples
wpfvb.netcontenttemplate

Set Diffrent DataContext to an Element in a ControlTemplate in WPF


I can't get any further.

My structure looks like this:

ViewModel (Class)
   Property Number (Class, iValue)
                Value, InputValidationInfo, etc.
   Property Icon (Class, iValue)
                Value, InputValidationInfo, etc.

The DataContext of the page is the ViewModel. There are input fields on the page. These are assigned to one of the iValues (Number, Icon). All input fields have a ContentTemplate. The ContentTemplate contains some elements which has bindings to the properties of the iValue-class.

<ControlTemplate TargetType="{x:Type Button}">
    <Border x:Name="border" Background="{TemplateBinding Background}">
        <DockPanel>
            <Border Width="10" Background="{Binding InputValidation, Converter={StaticResource InputValidationToBrushConverter}}" Margin="0">
                <Border.ToolTip>
                    <ToolTip Visibility="{Binding InputValidationInfoCount, Converter={StaticResource CountToVisibleConverter}}" >
                                        <ItemsControl ItemsSource="{Binding InputValidationInfo}"/>
                         </ToolTip>
                     </Border.ToolTip>
                 </Border>
                 <Border x:Name="ContentBorder" Margin="1">
                 <Grid>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="*"/>
                         <ColumnDefinition Width="Auto"/>
                     </Grid.ColumnDefinitions>
                     <ContentPresenter Margin="5 1 0 1" x:Name="myButtonContent" HorizontalAlignment="Left" VerticalAlignment="Center" TextElement.Foreground="{StaticResource ButtonForegroundBrush}"/>
                     <StackPanel x:Name="Buttons" Grid.Column="1" Orientation="Horizontal" Visibility="Collapsed">
                         <Button x:Name="ResetButton" Style="{StaticResource styleInputBoxSubButton}" Content="{StaticResource symbolCancel}" FontFamily="{StaticResource symbolCancelFF}" Command="{Binding ResetValueCommand}"/>
                     </StackPanel>
                 </Grid>
             </Border>
         </DockPanel>
    </Border>
</ControlTemplate>

And this is how it looks like:

<Button x:Name="btnIcon" Grid.Column="1" Grid.Row="2" DataContext="{Binding Icon}"
    Style="{StaticResource styleInputButton}" MinHeight="37"
    FontFamily="{Binding Value, Converter={StaticResource NumberToUserIconFontFamilyConverter}}"
    Content="{Binding Value, Converter={StaticResource NumberToUserIconConverter}}"
    Click="IconButton_Click"/>

enter image description here

My problem are the click events. The small [X] button is bound to the iValue classes with an ICommand. This works well. I can set the iCommand as binding in the ControlTemplate, because this is always the same iValue-property (ResetValueCommand).

But, a click of the "rest" of the actual button should call a method in the ViewModel. And the name of this method is not always the same. It cannot set in the ContentTemplate.

I cannot bind the command to the ViewModel, because the DataContext is already the iValue. I have tried to use the Click event. But this event is also triggered by clicking the [X]-button.

This button should be used often. An elegant solution is needed. The most simple thing would be if I could specify the data context and binding for a particular element in the ContentTemplate in page-XAML. Or specify the click event of an element in the ContentTemplate in page-XAML.


Solution

  • I cannot bind the command to the ViewModel, because the DataContext is already the iValue ...

    You can specify a source for the binding regardless of its DataContext:

    <Button x:Name="btnIcon" ...
            Command="{Binding DataContext.CommandPropertyOfViewModel, 
                RelativeSource={RelativeSource AncestorType=Page}}"/>