WPF: изменение свойства ControlTemplate из DataTemplate? - PullRequest
1 голос
/ 29 ноября 2009

Используя MVVM-подход к WPF, у меня есть класс модели представления с именем SubButton. Он оформлен следующим образом:

<!-- 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>

DataTrigger не работает. Selected - это обычное свойство .Net класса SubButton. Я получаю ошибку компиляции, потому что компилятор не может определить, откуда взялась цель rectBackground Это часть ControlTemplate, я не уверен, как это сказать? Что-то про DataContext?

1 Ответ

1 голос
/ 29 ноября 2009

То, что вы хотите, не возможно. WPF работает с NameScopes, а имя rectBackground находится вне области действия в DataTemplate. Исходное имя rectBackground будет только в области видимости внутри исходного ControlTemplate. Это удачно, потому что в противном случае вы не сможете использовать повторяющееся имя во всем приложении. Что вы можете сделать, это связать свойство Fill rectBackground со свойством Background RadioButton через TemplateBinding. Когда вы изменяете фон RadioButton где-либо еще в вашем коде, rectBackground получит эту кисть как Fill. Я немного изменил ваш код, чтобы проиллюстрировать это. Это будет легко изменить в вашей модели с помощью 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> 
...