简体   繁体   中英

WPF Custom Control with Dependency Property binding to DockPanel.Dock Attached Property not working

I'm attempting to create a custom control with 4 states (Top, Bottom, Left, Right), and each of these states needs to update the DockPanel.Dock attached property which is attached to an Image control in the control's template.

A portion of my control template is as follows:

<ControlTemplate TargetType="{x:Type library:IndicatorButton}">
    <DockPanel LastChildFill="True">
    <Image x:Name="Icon" 
        DockPanel.Dock="{TemplateBinding State}" Height="66" Width="87"
        HorizontalAlignment="Center" VerticalAlignment="Center" 
        Stretch="UniformToFill" Source="{DynamicResource HandIcon}"/>

    <Border Background="{x:Null}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            SnapsToDevicePixels="True" >
        <Rectangle Fill="Transparent"/>
    </Border>

And the “State” property is defined as a dependency property like so

public static readonly DependencyProperty StateProperty =
        DependencyProperty.Register("State", typeof(HandIndicatorStates),
        typeof(IndicatorButton),
        new FrameworkPropertyMetadata(HandIndicatorStates.None,
        OnIndicatorStateChanged){
    BindsTwoWayByDefault = true,
  });

HandIndicatorStates is an enum which is defined as follows

public enum HandIndicatorStates
{
    Left = 0,
    Right = 1,
    Top = 2,
    Bottom = 3,
    None = 4
}

And finally i'm defining the control in the xaml like so

<library:IndicatorButton State="Top" BorderBrush="Yellow" BorderThickness="5"/>

When I change the “State” property in the control definition, nothing happens. But when I remove the template binding in the control template and replace it with “Top”, “Bottom” etc I get the required results.

I'm sure this is something I'm not doing in the custom control code that I should be. I've omitted some stuff to try and keep this short and sweet, but if you need anything else please ask

Thank you for any help

Well, the DockPanel.Dock attached property is of type System.Windows.Controls.Dock while the property you are binding to is of your own custom enum type.

That is not going to work, and you should be getting a binding error in the output window in Visual Studio that indicates this.

To make it work, you can attach a IValueConverter to the binding, which simply maps between the different enum types.

I have written a very small program that shows how it can be done. There is no ControlTemplate or anything like that, but yours has nothing to do with the actual problem.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    public HandIndicatorStates State
    {
        get { return HandIndicatorStates.Top; }
    }
}

public enum HandIndicatorStates
{
    Left = 0,
    Right = 1,
    Top = 2,
    Bottom = 3,
    None = 4
}

public class StateToDockEnumConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
            object parameter, System.Globalization.CultureInfo culture)
    {
        HandIndicatorStates state = (HandIndicatorStates)value;

        if (state == HandIndicatorStates.None)
            return null; //??

        // Map from HandIndicatorStates to Dock enum by name.
        var dock = Enum.Parse(typeof(Dock), state.ToString());
        return dock;
    }

    public object ConvertBack(object value, 
        Type targetType, object parameter, 
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And the XAML:

<Window.Resources>
    <local:StateToDockEnumConverter x:Key="conv" />
</Window.Resources>

<DockPanel>
    <Button Content="Dock to top" 
            DockPanel.Dock="{Binding State, Converter={StaticResource conv}}" />

    <Button Content="Fill rest" />
</DockPanel>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM