Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 在按钮中';s控件模板,如何设置包含文本的颜色?_Wpf_Silverlight_Button_Controltemplate_Visualstatemanager - Fatal编程技术网

Wpf 在按钮中';s控件模板,如何设置包含文本的颜色?

Wpf 在按钮中';s控件模板,如何设置包含文本的颜色?,wpf,silverlight,button,controltemplate,visualstatemanager,Wpf,Silverlight,Button,Controltemplate,Visualstatemanager,使用Silverlight 4和WPF 4,我试图创建一个按钮样式,当按钮被鼠标悬停时,它会改变任何包含文本的文本颜色。由于我试图使其与Silverlight和WPF兼容,因此我使用的是可视化状态管理器: <Style TargetType="{x:Type Button}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Butt

使用Silverlight 4和WPF 4,我试图创建一个按钮样式,当按钮被鼠标悬停时,它会改变任何包含文本的文本颜色。由于我试图使其与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>

但如果按钮声明为:

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

尽管可视树(在snoop中检查时)是相同的(按钮->ContentPresenter->TextBlock),但需要注意的是,第一个版本中创建的TextBlock的数据上下文设置为“Hello,World”,而第二个版本中的TextBlock仅设置了其文本属性。我认为这与控件创建的顺序有关(第一个版本的按钮创建TextBlock,第二个版本的按钮可能首先创建TextBlock?真的不确定)

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

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


我非常感谢任何人能给予我的帮助和建议。

这是一个棘手的问题。前台是按钮的一个属性,它传递给内容演示者创建的控件。因为它是一个依赖属性,而不是模板中可用控件的属性,所以很难使用纯xaml为其设置动画

MSDN提供了一些关于如何更改前景色的示例。然而,听起来您并不想从代码中完成这项工作。(http://msdn.microsoft.com/en-us/library/system.windows.controls.button(VS.95.aspx)

按钮的默认模板会阻碍您。正如您所注意到的,button是一个无内容控件;这意味着设计师可以将一些随机的视觉对象推入其中。无内容强制前台属性成为模板的成员而不是控件,因为没有可设置颜色的Guaranteed组件。这就是为什么里面有一个内容演示者

现在你有两个选择。1.简单但不灵活(纯xaml),2。创建自己的控件,完成按钮所做的一切(需要代码和大量测试)

我将为您实施#1

如果修改按钮模板并删除内容演示者,则可以在其中放置两个文本块。一个是正常颜色,另一个是鼠标悬停在颜色上

<TextBlock x:Name="RedBlock" Text="{TemplateBinding Content}"      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Foreground="Red" Visibility="Collapsed"/>       
<TextBlock x:Name="BlueBlock" Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Foreground="#FF0027FF"/> 
这感觉像一个黑客,我可能不会在很多地方实现这个按钮。我想制作一个具有良好依赖性属性的按钮来绑定。高亮前景和文本各一个。如果有人试图将内容设置为字母数字值以外的任何值,我还想隐藏或至少抛出一个异常。但是,XAML是一样的,我会有不同的文本块用于不同的视觉状态

我希望这有帮助

祝你今天愉快


-Jeremiah

因此,经过进一步思考,我最终得出的解决方案是在按钮的控件模板中向ContentPresenter元素添加一个附加属性。附加属性接受颜色,当set检查内容呈现器的视觉树中是否有任何文本块时,将其前景属性设置为传入的值。这显然可以扩展/制作以处理其他元素,但目前它可以满足我的需要

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, 0, 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);
            }
        }
    }
公共静态类按钮连接属性
{
/// 
///ButtonTextForegroundProperty是用于调整按钮中包含的文本颜色的属性。
/// 
公共静态只读DependencyProperty按钮TextForeGroundProperty=DependencyProperty.RegisterAttached(
“ButtonExtForeground”,
类型(颜色),
类型(框架元件),
新的FrameworkPropertyMetadata(Color.FromArgb(255,0,0,0),FrameworkPropertyMetadata选项.AffectsRender,OnButtonTextForegroundChanged));
公共静态无效OnButtonTextForegroundChanged(DependencyObject o,DependencyPropertyChangedEventArgs e)
{
如果(例如,新值为颜色)
{
var brush=新的SolidColorBrush(((颜色)e.NewValue))作为笔刷;
如果(画笔!=null)
{
SetTextBlockForegroundColor(o作为框架元素,笔刷);
}
}
}
公共静态void SetButtonTextForeground(FrameworkElement fe,彩色)
{
var笔刷=新的SolidColorBrush(颜色);
SetTextBlockForegroundColor(fe,画笔);
}
公共静态void SetTextBlockForegroundColor(框架元素fe、画笔)
{
if(fe==null)
{
返回;
}
如果(fe是文本块)
{
((TextBlock)fe).前景=画笔;
<ControlTemplate TargetType="Button">
                <Border 
                    Margin="{TemplateBinding Margin}"
                    BorderBrush="{StaticResource BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    CornerRadius="2"
                    >

                    <TextBlock 
                        Margin="{TemplateBinding Padding}"
                        Text="{TemplateBinding Content}" 
                        Foreground="White"
                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>