修改:可以找到示例项目here。
我在主窗口中使用了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));
}
最后,这是我绑定到ListBox
构造函数中MainWindow
的数据:
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
?
答案 0 :(得分:3)
依赖项属性可以从多个来源获取其值,因此WPF使用precedence系统来确定应用哪个值。 “本地”值(使用SetValue或SetBinding提供)将覆盖创建模板提供的任何内容。
在您的情况下,您在构造函数中设置“本地”值(可能意味着它表现为默认值)。设置默认值的更好方法是在PropertyMetadata中提供它。
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(MyCustomBlock),
new FrameworkPropertyMetadata("<default>", TextChangedCallback));