我正在开发一个源自
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
。
对我来说,不同寻常的是您如何实现自定义依赖项对象类
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();
}