Reputation: 20364
I've written a small user control in WPF to wasily use a button with text and an image. It's called IconButton. Now I've added a property "Orientation" to allow the image be left or top of the text. But then, the image margin must be different. But I can't tell the image to set its margin according to the parent StackPanel's Orientation.
Here's the XAML code:
<Button
x:Class="MyNamespace.IconButton"
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"
x:Name="_this">
<Button.Template>
<ControlTemplate>
<Button
Padding="{TemplateBinding Padding}"
Style="{TemplateBinding Style}"
Command="{TemplateBinding Button.Command}">
<StackPanel Name="StackPanel" Orientation="{Binding Orientation, ElementName=_this}">
<Image Name="Icon"
Source="{Binding IconSource, ElementName=_this}"
VerticalAlignment="Center"
Margin="0,0,10,0">
<Image.Style>
<Style>
<Style.Triggers>
<Trigger Property="Button.IsEnabled" Value="False">
<Setter Property="Image.Opacity" Value="0.3"/>
</Trigger>
<Trigger Property="StackPanel.Orientation" Value="Vertical">
<Setter Property="Image.Margin" Value="0,0,0,10"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ContentPresenter
Visibility="{Binding ContentVisibility, ElementName=_this}"
RecognizesAccessKey="True"
Content="{Binding Content, ElementName=_this}"
VerticalAlignment="Center"/>
</StackPanel>
</Button>
</ControlTemplate>
</Button.Template>
</Button>
And this is the code-behind C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MyNamespace
{
public partial class IconButton : Button
{
public static DependencyProperty IconSourceProperty = DependencyProperty.Register(
"IconSource",
typeof(ImageSource),
typeof(IconButton));
public static DependencyProperty ContentVisibilityProperty = DependencyProperty.Register(
"ContentVisibility",
typeof(Visibility),
typeof(IconButton),
new PropertyMetadata(Visibility.Collapsed));
public static DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation",
typeof(Orientation),
typeof(IconButton),
new PropertyMetadata(Orientation.Horizontal));
public ImageSource IconSource
{
get { return (ImageSource) GetValue(IconSourceProperty); }
set { SetValue(IconSourceProperty, value); }
}
public Visibility ContentVisibility
{
get { return (Visibility) GetValue(ContentVisibilityProperty); }
set { SetValue(ContentVisibilityProperty, value); }
}
public Orientation Orientation
{
get { return (Orientation) GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
public IconButton()
{
InitializeComponent();
}
protected override void OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
ContentVisibility = (newContent is string ? !string.IsNullOrEmpty((string) newContent) : newContent != null) ? Visibility.Visible : Visibility.Collapsed;
}
}
}
I have no idea how to make it work. I'm still fairly new to WPF and those triggers drive me crazy.
My try is in the XAML code in line 26, where I want to query the StackPanel.Orientation value. It compiles, but it won't trigger anything.
The margins in this example are way too large, but only for better visibility of the issue.
Upvotes: 1
Views: 1213
Reputation: 43596
It seems yo have explicitly set the Margin
on the Image
, you should move that into a Style
Setter
otherwise a Trigger
wont change the value as it wont override a explicitly set value.
Also it may be easier to use a DataTrigger
to set the Margin
since you have the Orientation
dependancy property in the class.
Something like this should work for your Image
Style
.
<Image Name="Icon" Source="{Binding IconSource, ElementName=_this}" VerticalAlignment="Center">
<Image.Style>
<Style TargetType="{x:Type Image}">
<!-- move set margin to here -->
<Setter Property="Margin" Value="0,0,10,0"/>
<Style.Triggers>
<Trigger Property="Button.IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.3"/>
</Trigger>
<!-- set a DataTrigger to bind to the value of Orientation-->
<DataTrigger Binding="{Binding Orientation, ElementName=_this}" Value="Vertical">
<Setter Property="Margin" Value="0,0,0,10"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Upvotes: 2