We have a ton of Buttons with an Icon and Text across the App, and I am trying to extract a common style for all of them. I came up with this idea of deriving from a Button and have a couple of dependency properties. This custom button class has a style common to all the Buttons in our Application.
My Custom Button definition:
<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); }
}
}
}
And I am using this control as follows:
<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>
Things look good, however the trigger is not firing when the bounded data changes. If I apply the same trigger to the regular button, it seems to be working fine.
Could you please tell me if I am missing something?
EDIT: Found an elegant solution. Made use of Attached Properties
In your
CustomToolBarButton
, you are setting it'sDataContext
to the button itself(this.DataContext = this;
). By doing this you have stopped the propagation of the parent(parent control of your button, say grid or UserControl) data-context to your button(which contains theSelectedListItem
property).In case you just want to fix this, try to use
RelativeSource
orElementName
Binding to access the buttons parent control and then use it'sDataContext
to access theSelectedListItem
.The problem is happening as you have used a UserControl to extend the Button; as you said you have a ton of buttons, I would suggest you to create a
CustomControl
with template, like this; that way you won't have to mess with the DataContext propagation.Here is a blog explaining different ways of doing exactly what you want -
http://blogs.msdn.com/b/knom/archive/2007/10/31/wpf-control-development-3-ways-to-build-an-imagebutton.aspx
First of all you should never use
this.DataContext = this;
, ever.Secondly if you inherit from button you should not create a XAML file but a default style in the
Themes/Generic.xaml
resource dictionary (if you inherit fromUserControl
a file like this is fine).This will also mean that you will need to define a
Control.Template
in the style and hence should useTemplateBindings
instead of normal ones (or useRelativeSource
).As noted in another answer you may need to override the metadata.
Add this line of code to your static constructor
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.defaultstylekey.aspx