none
想通过资源来自定义按钮样式, 但是遇到了问题 RRS feed

  • 问题

  • <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="NormalFillBrush" Color="SkyBlue"/> <SolidColorBrush x:Key="PressedFillBrush" Color="Gray"/> <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}"> <Border x:Name="Border" CornerRadius="2" BorderThickness="1" > <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="MouseOver"> <Storyboard> <!--animation--> </Storyboard> </VisualState> <VisualState x:Name="Pressed" /> <VisualState x:Name="Disabled"> <Storyboard> <!--animations--> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Checked"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background)">

    <!--注1--> <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PressedFillBrush}"> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Unchecked" > <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background)"> <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NormalFillBrush}"> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Indeterminate" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border.BorderBrush> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="Gray" Offset="0" /> <GradientStop Color="Black" Offset="1" /> </LinearGradientBrush> </Border.BorderBrush> </Border> </ControlTemplate> </ResourceDictionary>

    这是在字典中定义的ToggleButton的template.

    <Page
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          xmlns:FlashPlayer="clr-namespace:FlashPlayer;assembly=FlashPlayer" x:Class="D2Build.flashTest.Flash" 
          mc:Ignorable="d" 
          d:DesignHeight="1080" d:DesignWidth="1920"
    	Title="Flash">
        <Grid Background="White">
            <Grid.Resources>
                <ResourceDictionary>
                    <ResourceDictionary.MergedDictionaries>
                        <ResourceDictionary Source="ToggleButtonDic.xaml"/>
                    </ResourceDictionary.MergedDictionaries>
                    <Style TargetType="ToggleButton">
                        <Setter Property="Template" Value="{StaticResource ComboBoxToggleButton}"/>
                    </Style>
                </ResourceDictionary>
            </Grid.Resources>
            <ToggleButton Width="600" Height="400">
                <ToggleButton.Resources>
                    <SolidColorBrush x:Key="NormalFillBrush" Color="Red"/>
                    <SolidColorBrush x:Key="PressedFillBrush" Color="Yellow"/>
                </ToggleButton.Resources>
            </ToggleButton>
        </Grid>
    </Page>
    

    这是使用该template的效果.

    此处, 我在定义ToggleButton时不仅引用了template, 还定义了与字典中Key相同的新的Brush, 以期望ToggleButton在运行的时候具有新的Brush用来处理不同状态下自身的Background属性.

    但是最终发现, 后面设置的Brush没有起作用.

    考虑到StaticResource特性, 我将上方两处(注1及其下方另一处)KeyFrame的资源引用设置为DynamicResource. 在这种情况下, ToggleButton运行起来没有Background; 感觉情况有点诡异, 实在搞不清楚为什么, 网上也查不出名堂, 希望有高人指点.

    不胜感激!

    2014年12月11日 7:03

答案

  • @Lymim,

     “后面设置的Brush没有起作用”

    WPF 里面会有一个就近的原则,我怀疑这个是你问题出现的原因,看下这个博客:

    http://www.cnblogs.com/Zhouyongh/archive/2011/08/01/2123610.html

    还不确定哪个在你的代码里没有起作用,不过你可以先参照就近原则看下是不是这个原因。



    Barry
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • 已标记为答案 Lymim 2015年1月13日 1:59
    2014年12月12日 10:23
    版主
  • 对于资源引用的就近原则我还是比较了解的, 但似乎我的问题并不出在这上面.

    我的代码的结构是:

    在ResourceDictionary中定义ToggleButton的Template, 其中的动画引用到了一个Brush(老Brush), Key为"NormalFillBrush";

    我在Page中定义了ToggleButton, 并引用了上方的Template, 并定义了新的Brush(新Brush), Key也是"NormalFillBrush";

    问题在于上方的引用是处于动画之中的, 因此:

    若使用StaticResource, 那么新Brush生效应该是由于 StaticResource的特性(我的理解:先定义后引用, 后面的同名定义都忽略);

    若使用DynamicResource, 那么新Brush和老Brush都不生效, 应该是由于Animation不允许动态值作为动画的起始点/终点(之前似乎遇到过类似的问题);

    现在我的问题是, 如何解决这个问题;

    现在我的替代方案是: 将ToggleButton的模板划分为表示各状态的不同的层, 将这些层全部添加到容器中, 在Animation中控制各层的透明度.

    • 已标记为答案 Lymim 2015年1月13日 1:59
    2014年12月15日 3:02

全部回复

  • @Lymim,

     “后面设置的Brush没有起作用”

    WPF 里面会有一个就近的原则,我怀疑这个是你问题出现的原因,看下这个博客:

    http://www.cnblogs.com/Zhouyongh/archive/2011/08/01/2123610.html

    还不确定哪个在你的代码里没有起作用,不过你可以先参照就近原则看下是不是这个原因。



    Barry
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • 已标记为答案 Lymim 2015年1月13日 1:59
    2014年12月12日 10:23
    版主
  • 对于资源引用的就近原则我还是比较了解的, 但似乎我的问题并不出在这上面.

    我的代码的结构是:

    在ResourceDictionary中定义ToggleButton的Template, 其中的动画引用到了一个Brush(老Brush), Key为"NormalFillBrush";

    我在Page中定义了ToggleButton, 并引用了上方的Template, 并定义了新的Brush(新Brush), Key也是"NormalFillBrush";

    问题在于上方的引用是处于动画之中的, 因此:

    若使用StaticResource, 那么新Brush生效应该是由于 StaticResource的特性(我的理解:先定义后引用, 后面的同名定义都忽略);

    若使用DynamicResource, 那么新Brush和老Brush都不生效, 应该是由于Animation不允许动态值作为动画的起始点/终点(之前似乎遇到过类似的问题);

    现在我的问题是, 如何解决这个问题;

    现在我的替代方案是: 将ToggleButton的模板划分为表示各状态的不同的层, 将这些层全部添加到容器中, 在Animation中控制各层的透明度.

    • 已标记为答案 Lymim 2015年1月13日 1:59
    2014年12月15日 3:02