【问题标题】:WPF Custom Control with Dependency Property binding to DockPanel.Dock Attached Property not working具有依赖属性绑定到 DockPanel.Dock 附加属性的 WPF 自定义控件不起作用
【发布时间】:2013-10-09 16:24:05
【问题描述】:

我正在尝试创建一个具有 4 种状态(上、下、左、右)的自定义控件,这些状态中的每一个都需要更新 DockPanel.Dock 附加属性,该属性附加到控件模板中的 Image 控件.

我的部分控件模板如下:

<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>

并且“State”属性被定义为像这样的依赖属性

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

HandIndicatorStates 是一个枚举,定义如下

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

最后我像这样在 xaml 中定义控件

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

当我更改控件定义中的“State”属性时,没有任何反应。但是当我删除控件模板中的模板绑定并将其替换为“顶部”、“底部”等时,我得到了所需的结果。

我确定这不是我应该在自定义控件代码中做的事情。我省略了一些内容以尽量保持简短和甜蜜,但如果您需要其他任何内容,请询问

感谢您的帮助

【问题讨论】:

  • 状态是否在开始时正确设置,即在您的问题中您已将状态设置为顶部,它是否在开始时设置在图像上?
  • 我猜是因为您的 DP 需要使用类型Dock,而您将其设置为类型HandIndicatorStates,无法转换为Dock

标签: c# wpf data-binding wpf-controls


【解决方案1】:

好吧,DockPanel.Dock 附加属性是 System.Windows.Controls.Dock 类型,而您要绑定的属性是您自己的自定义枚举类型。

这是行不通的,您应该在 Visual Studio 的输出窗口中收到一个绑定错误,表明这一点。

要使其工作,您可以将IValueConverter 附加到绑定,它只是在不同枚举类型之间进行映射。

我编写了一个非常小的程序来展示它是如何完成的。没有ControlTemplate 或类似的东西,但你的与实际问题无关。

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();
    }
}

还有 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>

【讨论】:

  • 谢谢!对自己没有弄清楚这一点有点失望。我想我会把它归结为昨天的日志日
猜你喜欢
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 2019-05-26
  • 2012-08-07
相关资源
最近更新 更多