自定义依赖属性找不到管理 FrameworkElement 或 FrameworkContentElement 异常

问题描述 投票:0回答:1

我正在开发一个源自

UserControl
TextBox

我有自定义

DependencyProperty HelperText
,如下所示:

public static readonly DependencyProperty HelperTextProperty = DependencyProperty.Register("HelperText", typeof(ICTextBoxHelperText), typeof(ICTextBox));
public ICTextBoxHelperText HelperText
{
    get { return (ICTextBoxHelperText)GetValue(HelperTextProperty); }
    set { SetValue(HelperTextProperty, value); }
}

这是类类型

ICTextBoxHelperText
并且有一些我在 UI 中需要的属性。

public class ICTextBoxHelperText : DependencyObject
{
    public static readonly DependencyProperty DefaultProperty = DependencyProperty.Register("Default", typeof(string), typeof(ICTextBoxHelperText));
    public static string GetDefault(DependencyObject d) => (string)d.GetValue(DefaultProperty);
    public static void SetDefault(DependencyObject d, string value) { d.SetValue(DefaultProperty, value); }

    public static readonly DependencyProperty InvalidProperty = DependencyProperty.Register("Invalid", typeof(string), typeof(ICTextBoxHelperText));
    public static string GetInvalid(DependencyObject d) => (string)d.GetValue(InvalidProperty);
    public static void SetInvalid(DependencyObject d, string value) { d.SetValue(InvalidProperty, value); }

    public static readonly DependencyProperty ValidatedProperty = DependencyProperty.Register("Validated", typeof(string), typeof(ICTextBoxHelperText));
    public static string GetValidated(DependencyObject d) => (string)d.GetValue(ValidatedProperty);
    public static void SetValidated(DependencyObject d, string value) { d.SetValue(ValidatedProperty, value); }

    public static readonly DependencyProperty AutoValidatedProperty = DependencyProperty.Register("AutoValidated", typeof(string), typeof(ICTextBoxHelperText));
    public static string GetAutoValidated(DependencyObject d) => (string)d.GetValue(AutoValidatedProperty);
    public static void SetAutoValidated(DependencyObject d, string value) { d.SetValue(AutoValidatedProperty, value); }
}

这是 UI 实现:

<!-- TextBox -->
<tx:ICTextBox x:Name="icTextBox"
              Width="240"
              Margin="0,20,0,0"
              Padding="0"
              VerticalAlignment="Center">

    <!-- Helper Text -->
    <tx:ICTextBox.HelperText>
        <tx:ICTextBoxHelperText Default="{Binding ElementName=icTextBox, Path=Text, UpdateSourceTrigger=PropertyChanged}"
                                Invalid="Invalid"
                                Validated="Validated"
                                AutoValidated="AutoValidated"/>
    </tx:ICTextBox.HelperText>
</tx:ICTextBox>

ICTextBoxHelperText
的静态值按预期工作并更新 UI。

问题出在绑定上。它根本不起作用,我遇到了这个 XAML 绑定异常

Cannot find governing FrameworkElement or FrameworkContentElement for target element

据我了解,这一定是这个

DataContext
没有
ICTextBoxHelperText
的问题,但是
HelperText
是在
FrameworkElement
内声明的,这是我从
TextBox
派生的控件。

是否有可能有一个

DependencyProperty
类型为
DependencyObject
的类型?我这样做了,所以我会得到一些类似类型的
DependencyProperties
的漂亮分组,而不是
DependencyProperties
中的一百个松散的
UserControl

c# .net wpf xaml data-binding
1个回答
0
投票

对我来说,不同寻常的是您如何实现自定义依赖项对象类

ICTextBoxHelperText
。您可以使用 Register 将它们注册为普通依赖属性,但 Getters 和 Setters 的语法是附加语法(使用 GetNNN/SetNNN 方法对而不是普通属性)。

然而,在 XAML 中,您似乎可以像使用“正常”非附加属性一样访问它们。而且没有理由让它们附加属性。我建议重写 ICTextBoxHelperText 类并从

Freezable
派生,这是一个轻量级实现,保证链接到可视化树的 DataContext - DependencyObject 继承则不然。由于您的类只包含附加数据,但没有控件模板/自己的视觉呈现,因此从 Control 或 UserControl 派生它是没有意义的。

所以我建议像这样重写ICTextBoxHelperText,看看它是否解决了缺少DataContext的问题。

public class ICTextBoxHelperText : Freezable
{
    public static readonly DependencyProperty DefaultProperty =
          DependencyProperty.Register(nameof(Default), typeof(string), typeof(ICTextBoxHelperText));
    
    public static string Default
    {
        get => (string)GetValue(DefaultProperty);
        set => SetValue(DefaultProperty, value); 
    }

    public static readonly DependencyProperty InvalidProperty =
          DependencyProperty.Register(nameof(Invalid), typeof(string), typeof(ICTextBoxHelperText));

    public static string Invalid
    {
        get => (string)GetValue(InvalidProperty);
        set => SetValue(InvalidProperty, value); 
    }

    public static readonly DependencyProperty ValidatedProperty =
          DependencyProperty.Register(nameof(Validated), typeof(string), typeof(ICTextBoxHelperText));

    public static string Validated
    {
        get => (string)GetValue(ValidatedProperty);
        set => SetValue(ValidatedProperty, value); 
    }

    public static readonly DependencyProperty AutoValidatedProperty =
          DependencyProperty.Register(nameof(AutoValidated), typeof(string), typeof(ICTextBoxHelperText));

    public static string AutoValidated
    {
        get => (string)GetValue(AutoValidatedProperty);
        set => SetValue(AutoValidatedProperty, value); 
    }

    protected override Freezable CreateInstanceCore() => new ICTextBoxHelperText();
}
© www.soinside.com 2019 - 2024. All rights reserved.