tags:

views:

401

answers:

1

Hi,

Using an MVVM approach to WPF, I have a view model class called SubButton. It is styled as follows:

<!-- SubNavButton Appearance -->
<ControlTemplate x:Key="SubNavButton" TargetType="{x:Type RadioButton}">
    <Grid Margin="5,5">
        <Rectangle x:Name="rectBackground" Fill="DimGray" Stroke="#FF000000" Width="150" Height="40" StrokeThickness="1"/>
        <TextBlock x:Name="txtContent" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" FontSize="16">
 <ContentPresenter />
        </TextBlock>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Fill" TargetName="rectBackground" Value="Red"/>
        </Trigger>
        <Trigger Property="IsChecked" Value="True">
            <Setter Property="Fill" TargetName="rectBackground" Value="Pink"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<!-- SubButton data template -->
<DataTemplate DataType="{x:Type VM:SubButton}">
    <RadioButton 
        Template="{StaticResource SubNavButton}"
        Content="{Binding TempText}"
        Command="{Binding SubFrameChanger.Command}"
        CommandParameter="{Binding Key}"
        GroupName="{Binding MenuGroup}"
        V:CreateCommandBinding.Command="{Binding SubFrameChanger}" />
    <DataTemplate.Triggers>
        <!-- This trigger doesn't work -->
        <DataTrigger Binding="{Binding Path=Selected}" Value="True">
            <Setter TargetName="rectBackground" Property="Fill" Value="Green"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

The DataTrigger doesn't work. "Selected" is a regular .Net property on the SubButton class. I am getting a compilation error because the compiler can't figure out where the "rectBackground" target comes from. It is part of the ControlTemplate, I'm not sure how to tell it that? Something about the data context?

+1  A: 

What you want is not possible. WPF works with NameScopes and the name rectBackground is out of scope in the DataTemplate. The original name rectBackground will only be in scope inside the original ControlTemplate. This is fortunate, because otherwise you would not be able to use a duplicate name throughout your entire application. What you can do is bind the Fill property of rectBackground to the RadioButton's Background property through TemplateBinding. When you change the RadioButton's Background anywhere else in your code rectBackground will get this Brush as its Fill. I modified your code somewhat to illustrate the point. It will be easy to change this to your model with a DataTemplate.

    <Window.Resources>
        <ControlTemplate x:Key="SubNavButton" TargetType="RadioButton">
            <Grid Margin="5,5">
                <Rectangle x:Name="rectBackground"
                       Fill="{TemplateBinding Background}" 
                       Stroke="#FF000000" Width="150" Height="40"
                       StrokeThickness="1"/>
                <TextBlock x:Name="txtContent" HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       FontFamily="Arial" FontSize="16">
                <ContentPresenter />
                </TextBlock>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Fill"
                        TargetName="rectBackground" Value="Red"/>
                </Trigger>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Fill" 
                        TargetName="rectBackground" Value="Pink"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
        <!-- The Style simulates the same behavior as the DataTemplate-->
        <Style TargetType="RadioButton">
            <Setter Property="Template" 
                Value="{StaticResource SubNavButton}"/>
            <Style.Triggers>
                <Trigger Property="IsFocused" Value="True">
                    <Setter Property="Background" Value="Green"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
       <RadioButton>one</RadioButton>
       <RadioButton>two</RadioButton>
    </StackPanel>
Dabblernl
Thanks, TemplateBinding makes a lot more sense, I was wondering how "outside world" stuff could ever get into a control :)However the DataTrigger still doesn't work yet...
evilfred
I think this isn't setting IsChecked properly (which should chnage the bg color): <DataTemplate DataType="{x:Type VM:SubButton}"> <RadioButton x:Name="rButton" Background="DimGray" Template="{StaticResource SubNavButton}" GroupName="{Binding MenuGroup}" /> <DataTemplate.Triggers> <DataTrigger Binding="{Binding Selected}" Value="True"> <Setter TargetName="rButton" Property="IsChecked" Value="True"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate>
evilfred
It is working in my example: simply change the Setter in the Style Trigger. The problem must be in the bound Selected property. Does it implement change notification correctly?
Dabblernl
I was out to lunch in my deleted comment... you're completely right, thanks! :)
evilfred
My example can be rewritten to set IsChecked in stead of the Background. rectBackground becomes Pink then.
Dabblernl