微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

wpf – 在按钮的控件模板中,如何设置包含文本的颜色?

使用Silverlight 4& WPF 4,我试图创建一个按钮样式,改变任何包含的文本的文本颜色,当按钮是mouSEOver’d.因为我试图使它兼容Silverlight& WPF,我正在使用视觉状态管理器:

<Style targettype="{x:Type Button}">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate targettype="Button">
            <Border x:Name="outerBorder" CornerRadius="4" BorderThickness="1" BorderBrush="#FF757679">
                <visualstatemanager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="normal" />
                        <VisualState x:Name="MouSEOver">
                            <Storyboard>
                                <ColorAnimation Duration="0" To="#FFFEFEFE"
                                                Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
                                                Storyboard.TargetName="contentPresenter"/> 
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </visualstatemanager.VisualStateGroups>
                <Grid>
                    <Border x:Name="Background" CornerRadius="3" BorderThickness="1" BorderBrush="Transparent">
                        <Grid>
                            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"/>
                        </Grid>
                    </Border>
                </Grid>
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

既然这是一个常规的旧按钮的模板,我知道这里不存在一个文本框,不知道这是甚么可能的.奇怪的是,如果按钮被声明为如下,文本颜色会改变:

<Button Content="Hello,World!" />

但是如果按钮被声明为:

<Button>
    <TextBlock Text="Hello,World!" /> <!-- Same result with <TextBlock>Hello,World </TextBlock> -->
</Button>

即使视觉树(在snoop中进行检查)是相同的(Button – > ContentPresenter – > TextBlock),与第一版本中创建的文本块的数据上下文设置为“Hello,World”的警告相反,第二个版本中的textblock仅设置其text属性.我假设这与控件创建的顺序有关(按钮创建TextBlock的第一个版本,在第二个版本中可能会首先创建文本框),真的不知道这一点).

在研究这个过程中,我看到了一些在Silverlight中工作的解决方案(比如用ContentControl替换ContentPresenter),但这在WPF(程序实际上是崩溃)中不起作用.

因为这是在按钮的控件模板中,如果可能,我想使用VSM,我认为也排除了显式地更改Button自己的Foreground属性(我不知道如何从模板中访问它? )

我真的很感激任何帮助,任何人都可以给予.

解决方法

所以经过一些思考之后,我最终得到的解决方案是在按钮控件模板中的ContentPresenter元素中添加一个附加的属性.附加的属性接受颜色,当设置检查任何TextBlocks的内容呈现者的可视树,并将Foreground属性设置为传入的值.这显然可以扩展/使其处理其他元素,但现在它工作为我所需要的

public static class ButtonAttachedProperties
    {
        /// <summary>
        /// ButtonTextForegroundProperty is a property used to adjust the color of text contained within the button.
        /// </summary>
        public static readonly DependencyProperty ButtonTextForegroundProperty = DependencyProperty.Registerattached(
            "ButtonTextForeground",typeof(Color),typeof(FrameworkElement),new FrameworkPropertyMetadata(Color.FromArgb(255,0),FrameworkPropertyMetadataOptions.AffectsRender,OnButtonTextForegroundChanged));

        public static void OnButtonTextForegroundChanged(DependencyObject o,DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue is Color)
            {
                var brush = new SolidColorBrush(((Color) e.NewValue)) as Brush;
                if (brush != null)
                {
                    SetTextBlockForegroundColor(o as FrameworkElement,brush);
                }
            }
        }

        public static void SetButtonTextForeground(FrameworkElement fe,Color color)
        {
            var brush = new SolidColorBrush(color);
            SetTextBlockForegroundColor(fe,brush);
        }

        public static void SetTextBlockForegroundColor(FrameworkElement fe,Brush brush)
        {
            if (fe == null)
            {
                return;
            }

            if (fe is TextBlock)
            {
                ((TextBlock)fe).Foreground = brush;
            }

            var children = VisualTreeHelper.GetChildrenCount(fe);
            if (children > 0)
            {
                for (int i = 0; i < children; i++)
                {
                    var child = VisualTreeHelper.GetChild(fe,i) as FrameworkElement;
                    if (child != null)
                    {
                        SetTextBlockForegroundColor(child,brush);
                    }
                }
            }
            else if (fe is ContentPresenter)
            {
                SetTextBlockForegroundColor(((ContentPresenter)fe).Content as FrameworkElement,brush);
            }
        }
    }

修改了模板:

<ContentPresenter x:Name="contentPresenter" 
                  ContentTemplate="{TemplateBinding ContentTemplate}" 
                  local:ButtonAttachedProperties.ButtonTextForeground="{StaticResource ButtonTextnormalColor}" />

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐