ygoe
ygoe

Reputation: 20364

Trigger from a parent element

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

Answers (1)

sa_ddam213
sa_ddam213

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>

enter image description here

Upvotes: 2

Related Questions