0

我们在整个应用程序中有大量带有图标和文本的按钮,我正在尝试为所有按钮提取通用样式。我想出了这个从 Button 派生的想法,并且有几个依赖属性。这个自定义按钮类具有我们应用程序中所有按钮共有的样式。

我的自定义按钮定义:

<Button x:Class="UIElements.Controls.CustomToolBarButton"
               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:telerik="http://schemas.telerik.com/2008/xaml/presentation" mc:Ignorable="d"
               >
<!--Style="{StaticResource ResourceKey=ToolBarButtonStyle}"-->
<StackPanel Orientation="Horizontal">
    <Image Source="{Binding Icon, Mode=TwoWay}" Style="{StaticResource ResourceKey=ToolBarButtonIconStyle}" />
    <TextBlock Text="{Binding DisplayText, Mode=TwoWay}" Style="{StaticResource ResourceKey=ToolBarButtonDisplayTextStyle}" />
</StackPanel>

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
//using Telerik.Windows.Controls;

namespace UIElements.Controls
{
    public partial class CustomToolBarButton : Button
    {
        public CustomToolBarButton()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(BitmapImage), typeof(Button), new PropertyMetadata(default(BitmapImage)));

        public BitmapImage Icon
        {
            get { return (BitmapImage)GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }

        public static readonly DependencyProperty DisplayTextProperty =
            DependencyProperty.Register("DisplayText", typeof(string), typeof(Button), new PropertyMetadata(default(string)));

        public string DisplayText
        {
            get { return (string) GetValue(DisplayTextProperty); }
            set { SetValue(DisplayTextProperty, value); }
        }
    }
}

我使用这个控件如下:

<Controls1:CustomToolBarButton Icon="{DynamicResource ImageSave}"
                        DisplayText="Test Display">
<Controls1:CustomToolBarButton.Style>
    <Style TargetType="Controls1:CustomToolBarButton">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding SelectedListItem.ListId}" Value="0" />
                </MultiDataTrigger.Conditions>
                <!--<Setter Property="Button.IsEnabled" Value="False" />-->
                <Setter Property="Background" Value="BurlyWood" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</Controls1:CustomToolBarButton.Style>

事情看起来不错,但是当有界数据更改时触发器没有触发。如果我将相同的触发器应用于常规按钮,它似乎工作正常。

如果我遗漏了什么,你能告诉我吗?

编辑: 找到了一个优雅的解决方案。使用附加属性

4

3 回答 3

0

首先,你永远不应该使用this.DataContext = this;, 永远。

其次,如果您从按钮继承,则不应创建 XAML 文件,而是在Themes/Generic.xaml资源字典中创建默认样式(如果您从UserControl这样的文件继承就可以了)。

这也意味着您需要Control.Template在样式中定义 a ,因此应该使用TemplateBindings而不是普通的(或使用RelativeSource)。

另一个答案中所述,您可能需要覆盖元数据。

于 2012-11-21T01:08:54.430 回答
0

将这行代码添加到您的静态构造函数中

DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomToolBarButton), new FrameworkPropertyMetadata(typeof(CustomToolBarButton)));

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.defaultstylekey.aspx

于 2012-11-20T02:11:28.803 回答
0

在您的CustomToolBarButton中,您将其设置DataContext为按钮本身(this.DataContext = this;)。通过这样做,您已停止将父级(按钮的父控件,例如网格或 UserControl)数据上下文传播到您的按钮(包含SelectedListItem属性)。

如果您只想解决此问题,请尝试使用RelativeSourceElementNameBinding 来访问按钮父控件,然后使用它DataContext来访问SelectedListItem.

<Grid x:Name="ParentGrid">

    <Controls1:CustomToolBarButton Icon="{DynamicResource ImageSave}"
                            DisplayText="Test Display">
    <Controls1:CustomToolBarButton.Style>
        <Style TargetType="Controls1:CustomToolBarButton">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding ElementName=ParentGrid,
                           Path=DataContext.SelectedListItem.ListId}" Value="0" />
                    </MultiDataTrigger.Conditions>
                    <!--<Setter Property="Button.IsEnabled" Value="False" />-->
                    <Setter Property="Background" Value="BurlyWood" />
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Controls1:CustomToolBarButton.Style>
</Grid>

当您使用 UserControl 扩展 Button 时,问题正在发生;正如您所说,您有很多按钮,我建议您创建一个CustomControl带有模板的模板,如下所示;这样您就不必弄乱 DataContext 传播。

这是一个博客,解释了完全按照您的意愿进行操作的不同方法-

http://blogs.msdn.com/b/knom/archive/2007/10/31/wpf-control-development-3-ways-to-build-an-imagebutton.aspx

于 2012-11-20T11:00:57.190 回答