WPF:DependencyProperty 适用于 TextBlock 但不适用于自定义控件
WPF: DependencyProperty works on TextBlock but not on custom control
编辑: 可以找到示例项目 here。
我在主 window 中使用 ListBox
,稍后我将其绑定到 ObservableCollection
。我同时使用 TextBlock
和绑定到集合的相同 属性 的自定义控件。我的问题是 TextBlock
得到正确更新,而自定义控件没有(它是默认构造的,但它的 Text
属性 永远不会被绑定更新)。
<ListBox Name="MyCustomItemList">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ItemText}"/>
<local:MyCustomBlock Text="{Binding ItemText}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我将 MyCustomBlock
实现为 System.Windows.Controls.Canvas
的子级,具有 Text
依赖性 属性:
public class MyCustomBlock : Canvas
{
public MyCustomBlock() => Text = "<default>";
public MyCustomBlock(string text) => Text = text;
private static void TextChangedCallback(DependencyObject o,
DependencyPropertyChangedEventArgs e)
{
...
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(MyCustomBlock),
new FrameworkPropertyMetadata("", TextChangedCallback));
}
最后,这是我在 MainWindow
构造函数中绑定到 ListBox
的数据:
public class MyCustomItem
{
public MyCustomItem(string text) => ItemText = text;
public string ItemText { get; set; }
}
public MainWindow()
{
InitializeComponent();
var list = new ObservableCollection<MyCustomItem>();
list.Add(new MyCustomItem("Hello"));
list.Add(new MyCustomItem("World"));
MyCustomItemList.ItemsSource = list;
}
我是不是忘记设置了什么?为什么 TextBlock.Text
看似正确更新但 MyCustomBlock.Text
却没有?
依赖属性可以从多个来源获取它们的值,因此 WPF 使用 precedence system to determine which value applies. "Local" values (provided using SetValue or SetBinding) 将覆盖创建模板提供的任何内容。
在您的情况下,您在构造函数中设置了一个 "local" 值(大概是打算将其用作默认值)。设置默认值的更好方法是在 PropertyMetadata 中提供它。
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(MyCustomBlock),
new FrameworkPropertyMetadata("<default>", TextChangedCallback));
编辑: 可以找到示例项目 here。
我在主 window 中使用 ListBox
,稍后我将其绑定到 ObservableCollection
。我同时使用 TextBlock
和绑定到集合的相同 属性 的自定义控件。我的问题是 TextBlock
得到正确更新,而自定义控件没有(它是默认构造的,但它的 Text
属性 永远不会被绑定更新)。
<ListBox Name="MyCustomItemList">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ItemText}"/>
<local:MyCustomBlock Text="{Binding ItemText}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我将 MyCustomBlock
实现为 System.Windows.Controls.Canvas
的子级,具有 Text
依赖性 属性:
public class MyCustomBlock : Canvas
{
public MyCustomBlock() => Text = "<default>";
public MyCustomBlock(string text) => Text = text;
private static void TextChangedCallback(DependencyObject o,
DependencyPropertyChangedEventArgs e)
{
...
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(MyCustomBlock),
new FrameworkPropertyMetadata("", TextChangedCallback));
}
最后,这是我在 MainWindow
构造函数中绑定到 ListBox
的数据:
public class MyCustomItem
{
public MyCustomItem(string text) => ItemText = text;
public string ItemText { get; set; }
}
public MainWindow()
{
InitializeComponent();
var list = new ObservableCollection<MyCustomItem>();
list.Add(new MyCustomItem("Hello"));
list.Add(new MyCustomItem("World"));
MyCustomItemList.ItemsSource = list;
}
我是不是忘记设置了什么?为什么 TextBlock.Text
看似正确更新但 MyCustomBlock.Text
却没有?
依赖属性可以从多个来源获取它们的值,因此 WPF 使用 precedence system to determine which value applies. "Local" values (provided using SetValue or SetBinding) 将覆盖创建模板提供的任何内容。
在您的情况下,您在构造函数中设置了一个 "local" 值(大概是打算将其用作默认值)。设置默认值的更好方法是在 PropertyMetadata 中提供它。
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(MyCustomBlock),
new FrameworkPropertyMetadata("<default>", TextChangedCallback));