WPF:从 DataTemplate 修改 ControlTemplate 属性?

发布于 2024-08-12 18:25:19 字数 1991 浏览 5 评论 0原文

使用 WPF 的 MVVM 方法,我有一个名为 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 不起作用。 SelectedSubButton 类上的常规 .Net 属性。我收到编译错误,因为编译器无法确定 rectBackground 目标来自何处。它是 ControlTemplate 的一部分,我不知道如何告诉它?有关 DataContext 的信息吗?

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 DataContext?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情换悲伤 2024-08-19 18:25:19

你想要的东西是不可能的。 WPF 使用 NameScopes,并且名称 rectBackground 超出了 DataTemplate 的范围。原始名称 rectBackground 将仅在原始 ControlTemplate 内的范围内。这是幸运的,因为否则您将无法在整个应用程序中使用重复的名称。
您可以做的就是通过 TemplateBinding 将 rectBackground 的 Fill 属性绑定到 RadioButton 的 Background 属性。当您在代码中的其他任何位置更改 RadioButton 的背景时, rectBackground 将获取此画笔作为其填充。我稍微修改了你的代码来说明这一点。使用 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> 

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> 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文