代码之家  ›  专栏  ›  技术社区  ›  Alan Wayne

如何使用basedon在generic.xaml中模板切换按钮?

  •  0
  • Alan Wayne  · 技术社区  · 6 年前

    WPF C.XAML

    在generic.xaml中,我有多种表单样式:

      <Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Grid>
                            <Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="true">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    所有这些切换按钮之间的唯一区别是路径定义和填充颜色。

    这种样式是否可以在只需要提供路径和填充颜色的情况下进行模板化/简化?

    这是符合以下原则的:

    <Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
        <Setter Property = "Path" Value="InsideQuarter3"/>
        <Setter Property = "Fill" Value="DarkOrange"/>
    </Style>
    

    谢谢你的帮助。

    编辑第1页 好吧,我以为我有——我错了。下面的代码将正确设置路径数据和填充属性。但是,只有第一个创建的toggleButton保留“mouseover”和其他controltemplate.triggers。我需要 所有的切换按钮 在RingControl中尊重自己的触发器。

      public static class ButtonProperties
        {
            public static Color GetMyForegroundColor(DependencyObject obj)
            {
                return (Color)obj.GetValue(MyForegroundColorProperty);
            }
    
            public static void SetMyForegroundColor(DependencyObject obj, Color value)
            {
                obj.SetValue(MyForegroundColorProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for MyForegroundColor.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty MyForegroundColorProperty =
                DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
    
    
    
            public static Geometry GetData(DependencyObject obj)
            {
                return (Geometry)obj.GetValue(DataProperty);
            }
    
            public static void SetData(DependencyObject obj, Geometry value)
            {
                obj.SetValue(DataProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty DataProperty =
                DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));
    
    
    
            public static Brush GetFill(DependencyObject obj)
            {
                return (Brush)obj.GetValue(FillProperty);
            }
    
            public static void SetFill(DependencyObject obj, Brush value)
            {
                obj.SetValue(FillProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for Fill.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty FillProperty =
                DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));
    
        }
    

    generic.xaml--基本按钮样式

      <Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
            <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Grid>
                        <TextBlock Text="Some Text">
                            <TextBlock.Foreground>
                                <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
                            </TextBlock.Foreground>
                        </TextBlock>
    
                            <Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}" 
                                  Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}" 
                                  Stroke="Black"/>
    
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" 
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="true">
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    generic.xaml--修改按钮样式1

     <Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
            <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
            <Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
        </Style>
        <Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
            <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
            <Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
        </Style>
        <Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
            <Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
            <Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
        </Style>
    

    generic.xaml--在自定义控件ringControl中使用modifiedButtonStyles

     <Style TargetType="{x:Type local:RingButtons2}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:RingButtons2}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
    
                        <Viewbox>
                            <Grid>
                                <!--Outer Rim -->
                                <Path Data="{StaticResource OuterRim}"  Fill="Silver" Stroke="Black" />
                                <Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />
    
                                <ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
                                <ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
                                <ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
      ........................................................
      </Grid>
                            </Viewbox>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    使用用户界面中的RingControl2:

           <w:RingButtons2/>
    

    似乎单击RingButtons2控件中的任何位置都只会导致第一个定义的ToggleButton响应——而不是其他任何响应。

    如何修复此问题,以使每个切换按钮独立于其他按钮并尊重其自己的ControlTemplate触发器?

    再次感谢。

    编辑第2页

    从baseButtonStyle中删除文本块定义后,

     <TextBlock Text="Some Text">
                            <TextBlock.Foreground>
                                <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
                            </TextBlock.Foreground>
                        </TextBlock>
    

    所有的作品!为什么会这样??

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Mark Feldman    6 年前

    如果目标控件具有可用于这些自定义绑定的依赖项属性,则可以使用TemplateBinding,下面是一个示例:

        <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="Blue" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    

    <Grid>
        <Button Style="{StaticResource ModifiedButtonStyle}" />
    </Grid>
    

    但是,在上面给出的示例中,您使用的是模板中的路径和填充,我猜这些模板没有关联的属性。在这种情况下,您可以选择创建一个新控件并将这些属性添加到该控件中,或者最好使用附加属性。对于后者,您将创建如下附加属性:

    public static class ButtonProperties
    {
        public static Color GetMyForegroundColor(DependencyObject obj)
        {
            return (Color)obj.GetValue(MyForegroundColorProperty);
        }
    
        public static void SetMyForegroundColor(DependencyObject obj, Color value)
        {
            obj.SetValue(MyForegroundColorProperty, value);
        }
    
        // Using a DependencyProperty as the backing store for MyForegroundColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyForegroundColorProperty =
            DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
    }
    

    然后在XAML中引用并重写它:

    <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <TextBlock Text="Some Text">
                        <TextBlock.Foreground>
                            <SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
                                Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
                        </TextBlock.Foreground>
                    </TextBlock>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
        <Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
    </Style>
    

    这些或多或少是相同的,只是在第一种情况下,您使用的是控件中已经存在的属性(或者创建一个拥有这些属性的新控件),而在第二种情况下,您声明并将它们附加到外部的现有控件。