如何在XAML样式中正确设置BasedOn

时间:2014-06-24 09:09:18

标签: wpf xaml

我将其作为样式模板:

<Style x:Key="myDogToggleButton1" TargetType="ToggleButton" BasedOn="{x:Null}">
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Grid>
                    <Image Name="Normal" Source="/images/dogs/dog1.png"/>
                    <Image Name="Pressed" Source="/images/dogs/dog3.png" Visibility="Hidden"/>
                    <Image Name="Disabled" Source="images/dogs/dog5.png" Visibility="Hidden"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                        <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                        <Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在我想要另一个基于上一个的,这不起作用:

<Style x:Key="myDogToggleButton2" TargetType="ToggleButton" BasedOn="{DynamicResource myDogToggleButton1}">
    <Setter Property="Normal" Value="/images/dogs/dog2.png" />
    <Setter Property="Pressed" Value="/images/dogs/dog2.png" />
    <Setter Property="Disabled" Value="/images/dogs/dog2.png" />
</Style>

我得到的错误信息是:

The member "Pressed" is not recognized or is not accessible.
The member "Normal" is not recognized or is not accessible.
The member "Disabled" is not recognized or is not accessible.

我怀疑我的不同风格调用是错误的,所以请指出错误。

2 个答案:

答案 0 :(得分:2)

试试这个

<强>资源

<Window.Resources>
    <Style x:Key="myDogToggleButton1" TargetType="ToggleButton">
        <Style.Resources>
            <BitmapImage x:Key="Normal" UriSource="Images/darblue_tab.png"/>
            <BitmapImage x:Key="Pressed" UriSource="Images/img-whitebg.png" />
            <BitmapImage x:Key="Disabled" UriSource="Images/img-greenbg.png"/>
        </Style.Resources>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid>
                        <Image Name="Normal" Source="{DynamicResource ResourceKey=Normal}" Stretch="Fill"/>
                        <Image Name="Pressed" Source="{DynamicResource ResourceKey=Pressed}" Visibility="Hidden"/>
                        <Image Name="Disabled" Source="{DynamicResource ResourceKey=Disabled}" Visibility="Hidden"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                            <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                            <Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="myDogToggleButton2" TargetType="ToggleButton" BasedOn="{StaticResource myDogToggleButton1}">
        <Style.Resources>
            <BitmapImage x:Key="Normal" UriSource="Images/img-darkbg.png" />
            <BitmapImage x:Key="Pressed" UriSource="Images/Screenshot_5.png"/>
            <BitmapImage x:Key="Disabled" UriSource="Images/img-bluebg.png"/>
        </Style.Resources>
    </Style>
</Window.Resources>

Xaml

<Grid>
    <ToggleButton HorizontalAlignment="Left" Style="{StaticResource myDogToggleButton1}"/>
    <ToggleButton  HorizontalAlignment="Right" Style="{StaticResource myDogToggleButton2}"/>
</Grid>

<强>更新 使用单一风格。

<Grid>
    <ToggleButton Height="300" Width="300" HorizontalAlignment="Left" Style="{StaticResource myDogToggleButton1}"/>
    <ToggleButton  Height="300" Width="300" Style="{StaticResource myDogToggleButton1}" HorizontalAlignment="Right">
        <ToggleButton.Resources>
            <BitmapImage x:Key="Normal" UriSource="Images/img-darkbg.png" />
            <BitmapImage x:Key="Pressed" UriSource="Images/Screenshot_5.png"/>
            <BitmapImage x:Key="Disabled" UriSource="Images/img-bluebg.png"/>
        </ToggleButton.Resources>
    </ToggleButton>
</Grid>

enter image description here

答案 1 :(得分:1)

这个解决方案是使用附加属性,因为您无法访问派生样式中的作用域元素

首先编写一个帮助类

class Helper:DependencyObject
{
    public static object GetNormal(DependencyObject obj)
    {
        return (object)obj.GetValue(NormalProperty);
    }

    public static void SetNormal(DependencyObject obj, object value)
    {
        obj.SetValue(NormalProperty, value);
    }

    // Using a DependencyProperty as the backing store for Normal.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty NormalProperty =
        DependencyProperty.RegisterAttached("Normal", typeof(object), typeof(Helper), new PropertyMetadata(null));



    public static object GetPressed(DependencyObject obj)
    {
        return (object)obj.GetValue(PressedProperty);
    }

    public static void SetPressed(DependencyObject obj, object value)
    {
        obj.SetValue(PressedProperty, value);
    }

    // Using a DependencyProperty as the backing store for Pressed.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PressedProperty =
        DependencyProperty.RegisterAttached("Pressed", typeof(object), typeof(Helper), new PropertyMetadata(null));



    public static object GetDisabled(DependencyObject obj)
    {
        return (object)obj.GetValue(DisabledProperty);
    }

    public static void SetDisabled(DependencyObject obj, object value)
    {
        obj.SetValue(DisabledProperty, value);
    }

    // Using a DependencyProperty as the backing store for Disabled.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DisabledProperty =
        DependencyProperty.RegisterAttached("Disabled", typeof(object), typeof(object), new PropertyMetadata(null));
}

然后按如下方式修改样式。 l:将引用你的命名空间。

    <Style x:Key="myDogToggleButton1"
           TargetType="ToggleButton"
           BasedOn="{x:Null}"
           xmlns:l="clr-namespace:CSharpWPF">
        <Setter Property="FocusVisualStyle"
                Value="{x:Null}" />
        <Setter Property="l:Helper.Normal"
                Value="/images/dogs/dog1.png" />
        <Setter Property="l:Helper.Pressed"
                Value="/images/dogs/dog3.png" />
        <Setter Property="l:Helper.Disabled"
                Value="/images/dogs/dog5.png" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid>
                        <Image Name="Normal"
                               Source="{TemplateBinding l:Helper.Normal}" />
                        <Image Name="Pressed"
                               Source="{TemplateBinding l:Helper.Pressed}"
                               Visibility="Hidden" />
                        <Image Name="Disabled"
                               Source="{TemplateBinding l:Helper.Disabled}"
                               Visibility="Hidden" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed"
                                 Value="True">
                            <Setter TargetName="Normal"
                                    Property="Visibility"
                                    Value="Hidden" />
                            <Setter TargetName="Pressed"
                                    Property="Visibility"
                                    Value="Visible" />
                        </Trigger>
                        <Trigger Property="IsEnabled"
                                 Value="False">
                            <Setter TargetName="Normal"
                                    Property="Visibility"
                                    Value="Hidden" />
                            <Setter TargetName="Disabled"
                                    Property="Visibility"
                                    Value="Visible" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="myDogToggleButton2"
           TargetType="ToggleButton"
           BasedOn="{StaticResource myDogToggleButton1}"
           xmlns:l="clr-namespace:CSharpWPF">
        <Setter  Property="l:Helper.Normal"
                 Value="/images/dogs/dog2.png" />
        <Setter Property="l:Helper.Pressed"
                Value="/images/dogs/dog2.png" />
        <Setter Property="l:Helper.Disabled"
                Value="/images/dogs/dog2.png" />
    </Style>

有用的好处

这种方法的一个有用的好处。您也可以声明内联值而不是定义新样式。例如

<ToggleButton l:Helper.Normal="image-normal.jpg" 
              l:Helper.Pressed="image-pressed.jpg" 
              l:Helper.Disabled="image-disabled.jpg" 
              Style="{StaticResource myDogToggleButton1}"/>

请注意我使用的是基本样式,如果您只需为一个按钮创建一个新样式,这种方法很有用。

<强>附加

下面是切换按钮查找VisualStateManager.VisualStateGroups的原始模板,您可以根据状态Normal, Pressed, Disabled来操纵属性值,甚至更多

<Style TargetType="ToggleButton">
  <Setter Property="Background" Value="#FF1F3B53"/>
  <Setter Property="Foreground" Value="#FF000000"/>
  <Setter Property="Padding" Value="3"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="BorderBrush">
      <Setter.Value>
          <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
              <GradientStop Color="#FFA3AEB9" Offset="0"/>
              <GradientStop Color="#FF8399A9" Offset="0.375"/>
              <GradientStop Color="#FF718597" Offset="0.375"/>
              <GradientStop Color="#FF617584" Offset="1"/>
          </LinearGradientBrush>
      </Setter.Value>
  </Setter>
  <Setter Property="Template">
      <Setter.Value>
          <ControlTemplate TargetType="ToggleButton">
              <Grid>
                  <vsm:VisualStateManager.VisualStateGroups>
                      <vsm:VisualStateGroup x:Name="CommonStates">
                          <vsm:VisualState x:Name="Normal"/>
                          <vsm:VisualState x:Name="MouseOver">
                              <Storyboard>
                                  <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity" To="1"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#F2FFFFFF"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#CCFFFFFF"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#7FFFFFFF"/>
                              </Storyboard>
                          </vsm:VisualState>
                          <vsm:VisualState x:Name="Pressed">
                              <Storyboard>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#FF6DBDD1"/>
                                  <DoubleAnimation Duration="0" Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity" To="1"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" To="#D8FFFFFF"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" To="#C6FFFFFF"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" To="#8CFFFFFF"/>
                                  <ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" To="#3FFFFFFF"/>
                              </Storyboard>
                          </vsm:VisualState>
                          <vsm:VisualState x:Name="Disabled">
                              <Storyboard>
                                  <DoubleAnimation Duration="0" Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity" To=".55"/>
                              </Storyboard>
                          </vsm:VisualState>
                      </vsm:VisualStateGroup>
                      <vsm:VisualStateGroup x:Name="CheckStates">
                          <vsm:VisualState x:Name="Checked">
                              <Storyboard>
                                  <PointAnimation Duration="0" To="0.7,1" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(LinearGradientBrush.StartPoint)"/>
                                  <PointAnimation Duration="0" To="0.7,0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(LinearGradientBrush.EndPoint)"/>
                              </Storyboard>
                          </vsm:VisualState>
                          <vsm:VisualState x:Name="Unchecked"/>
                      </vsm:VisualStateGroup>
                      <vsm:VisualStateGroup x:Name="FocusStates">
                          <vsm:VisualState x:Name="Focused">
                              <Storyboard>
                                  <DoubleAnimation Duration="0" Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1"/>
                              </Storyboard>
                          </vsm:VisualState>
                          <vsm:VisualState x:Name="Unfocused" />
                      </vsm:VisualStateGroup>
                  </vsm:VisualStateManager.VisualStateGroups>
                  <Border x:Name="Background" CornerRadius="3" Background="White" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
                      <Grid Background="{TemplateBinding Background}"  Margin="1">
                          <Border Opacity="0"  x:Name="BackgroundAnimation" Background="#FF448DCA" />
                          <Rectangle x:Name="BackgroundGradient" >
                              <Rectangle.Fill>
                                  <LinearGradientBrush StartPoint=".7,0" EndPoint=".7,1">
                                      <GradientStop Color="#FFFFFFFF" Offset="0" />
                                      <GradientStop Color="#F9FFFFFF" Offset="0.375" />
                                      <GradientStop Color="#E5FFFFFF" Offset="0.625" />
                                      <GradientStop Color="#C6FFFFFF" Offset="1" />
                                  </LinearGradientBrush>
                              </Rectangle.Fill>
                          </Rectangle>
                      </Grid>
                  </Border>
                  <ContentPresenter
                          x:Name="contentPresenter"
                          Content="{TemplateBinding Content}"
                          ContentTemplate="{TemplateBinding ContentTemplate}"
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                          Margin="{TemplateBinding Padding}"/>
                  <Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
                  <Rectangle x:Name="FocusVisualElement" RadiusX="2" RadiusY="2" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
              </Grid>
          </ControlTemplate>
      </Setter.Value>
  </Setter>
</Style>

此处有更多相关信息http://msdn.microsoft.com/en-us/library/cc296245(v=vs.95).aspx