【问题标题】:How to set another control style when they are created in ItemsControl在 ItemsControl 中创建控件时如何设置其他控件样式
【发布时间】:2014-03-13 23:32:38
【问题描述】:

下面显示了两个按钮。当鼠标悬停在第二个按钮上时,我想将第一个边框笔刷更改为白色。

<ItemsControl ItemsSource="{Binding Path=ModuleCollection}"  >
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0">
                <Button Content="{Binding ModuleName}" Template="{StaticResource navModuleButton}"/>
                <Button Template="{StaticResource CloseButtonStyle}"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我相信可以通过如下方式在第一个按钮上使用数据触发器来完成,但为了做到这一点,我需要命名第二个按钮,不知道如何动态命名。

<DataTrigger Binding="{Binding ElementName=closeBtn1, Path=IsMouseOver}" Value="True">
     <Setter Property="BorderBrush" TargetName="btnBorder" Value="#FFFFFFFF"/>
</DataTrigger>

如何做到这一点?

[编辑]

这是您将看到的第一个按钮的模板 btnBorder 是我要更改颜色的边框。

<ControlTemplate x:Key="navModuleButton" TargetType="{x:Type Button}">
    <Border x:Name="btnBorder" RenderTransformOrigin="0.5,0.5" BorderThickness="1,1,1,1" CornerRadius="0,0,7,0">
        <Grid x:Name="Grid" RenderTransformOrigin="0.5,0.5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>
            <Border x:Name="Border1" RenderTransformOrigin="0.5,0.5" BorderThickness="0.5,0.5,0.5,0.5" CornerRadius="0,0,7,0">
                <Border.Background>
                    <LinearGradientBrush StartPoint="0,0.5"  EndPoint="1,0.5">
                        <LinearGradientBrush.RelativeTransform>
                            <TransformGroup>
                                <ScaleTransform ScaleX="1" ScaleY="1" />
                                <RotateTransform Angle="90" />
                            </TransformGroup>
                        </LinearGradientBrush.RelativeTransform>
                    </LinearGradientBrush>
                </Border.Background>
            </Border>
            <DockPanel Name="myContentPresenterDockPanel">
                <ContentPresenter x:Name="myContentPresenter" Margin="10,0,21,0"  
                                  Content="{TemplateBinding  Content}" 
                                  HorizontalAlignment="Center" VerticalAlignment="Center" 
                                  TextBlock.Foreground="White" />
            </DockPanel>
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" TargetName="btnBorder" Value="#FFFFFFFF"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsEnabled" Value="False"/>
            </MultiTrigger.Conditions>
            <Setter Property ="Opacity" Value="0.30" />
        </MultiTrigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsPressed" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Border1">
                <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                        <LinearGradientBrush.RelativeTransform>
                            <TransformGroup>
                                <TranslateTransform X="0" Y="0"/>
                                <ScaleTransform ScaleX="1" ScaleY="1"/>
                                <SkewTransform AngleX="0" AngleY="0"/>
                                <RotateTransform Angle="90"/>
                                <TranslateTransform X="0" Y="0"/>
                                <TranslateTransform X="0" Y="0"/>
                            </TransformGroup>
                        </LinearGradientBrush.RelativeTransform>
                        <LinearGradientBrush.GradientStops>
                            <GradientStopCollection>
                                <GradientStop Color="#837C7C7C" Offset="0"/>
                                <GradientStop Color="#83343434" Offset="0.99496336996337187"/>
                                <GradientStop Color="#83343434" Offset="0.523844744998591"/>
                                <GradientStop Color="#837C7C7C" Offset="0.48045224006762494"/>
                            </GradientStopCollection>
                        </LinearGradientBrush.GradientStops>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
            <Setter Property="Cursor" Value="Hand" TargetName="Grid"/>
            <Setter Property="BitmapEffect" TargetName="Border1">
                <Setter.Value>
                    <OuterGlowBitmapEffect GlowColor="Blue"/>
                </Setter.Value>
            </Setter>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

【问题讨论】:

  • 为什么要“动态命名”第二个按钮(以及您的意思)?
  • 您会看到两个按钮,当我将鼠标悬停在第二个按钮上时,我希望第一个按钮突出显示它的边框。我为每个按钮都有一个 ControlTemplate,在模板中有一个名为 btnBorder 的边框,我想更改它的颜色。
  • 当通过数据触发器引用另一个控件时,您需要使用另一个控件的名称,不是吗?由于这些按钮是从 ItemsControl 动态创建的,因此必须动态创建唯一的名称。我认为

标签: wpf xaml


【解决方案1】:

您可以在触发器中使用SourceName 属性,如下所示:

<DataTemplate>
    <Grid Margin="0">
        <Button x:Name="btnModule"
                Content="{Binding ModuleName}" 
                Template="{StaticResource navModuleButton}"/>

        <Button x:Name="btnClose"
                Template="{StaticResource CloseButtonStyle}"/>
     </Grid>

     <DataTemplate.Triggers>
         <Trigger SourceName="btnClose" Property="IsMouseOver">
             <Setter TargetName="btnModule" Property="BorderBrush" Value="White"/>
         </Trigger>
     </DataTemplate.Triggers>
</DataTemplate>

不用担心名称,WPF 会处理这些,因为 DataTemplate 有自己的 Name Scope

编辑:您的按钮 ControlTemplate 错误。

ControlTemplate 的定义方式应使其中的 Visual 元素的属性“绑定”到应用模板的 Control 的属性。

换句话说,您的btnBorder 应该取决于应用模板的“父模板项”控件的属性,在本例中为btnModule

为此,一种常见的方法是在 ControlTemplate 中使用TemplateBinding,如下所示:

 <Border x:Name="btnBorder" 
         RenderTransformOrigin="0.5,0.5" 
         BorderThickness="1,1,1,1" 
         CornerRadius="0,0,7,0"
         BorderBrush="{TemplateBinding BorderBrush}"> <!-- See the TemplateBinding here -->

这会将btnBorder.BorderBrush 属性绑定到父级的BorderBrush(在本例中为btnModule.BorderBrush

【讨论】:

  • 有道理,但我尝试过但没有成功,我可以专门针对组件 btnBorder 吗?我在上面发布了一个编辑,其中包括 btnModule ControlTemplate。
  • @Hank 不,您不能从不同的 NameScope 访问 UI 元素。查看我的编辑
  • 其实还是和这个有关,假设在模板中有两个边框如果我想在两个边框上都换刷子怎么办?
猜你喜欢
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多