我试图了解通知如何在WPF中用于附加属性。
例如,考虑ScrollViewer.CanContentScrollProperty属性。
假设我们有以下列表框
<ListBox x:Name="MainListBox"
Grid.Row="1"
ScrollViewer.CanContentScroll="False">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CustomerID}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
并且在Window代码中,我们将编写以下代码
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MainListBox.SetValue(ScrollViewer.CanContentScrollProperty, true);
}
执行Button_Click_1之后,ListBox将自动切换到CanContentScroll = true模式,但是尚不清楚ScrollViewer如何接收已连接属性的值已更改的信息。可以假设通过函数FrameworkPropertyMetadata(PropertyChangedCallback属性ChangedCallback),但事实是,属性ScrollViewer.CanContentScrollProperty没有定义PropertyChanged函数。
这里是此属性的声明代码。
public class ScrollViewer : ContentControl
...
public static readonly DependencyProperty CanContentScrollProperty = DependencyProperty.RegisterAttached(
nameof (CanContentScroll), typeof (bool), typeof (ScrollViewer),
(PropertyMetadata) new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));
可以看出,用于更改的功能未注册。
然后ScrollViewer如何知道ScrollViewer.CanContentScrollProperty属性已更改?
不幸的是,我最近一次使用WPF玩了一段时间,但从我记得/发现的结果来看,他们没有使用INotifyPropertyChanged。
INotifyPropertyChanged仅用于广播模型中的更改(基于您的数据)。
UI控件继承自DependencyObject类-这是其魔术性来源的一部分。另一部分是UI控件的属性使用DependencyProperty(如您附加的属性)。
[https://docs.microsoft.com/en-us/dotnet/desktop-wpf/data/data-binding-overview的一些引号:
目标属性必须是依赖项属性。大多数UIElement属性是依赖属性,大多数依赖属性除了只读的,默认情况下支持数据绑定。 (仅类型从DependencyObject派生的可以定义依赖项属性;和所有UIElement类型都从DependencyObject派生。)
和
要检测源更改(适用于OneWay和TwoWay绑定,source必须实现适当的属性更改通知INotifyPropertyChanged之类的机制。请参阅如何:实施属性更改通知的示例INotifyPropertyChanged实现。
然后您可以找到:
虽然未在图中显示,但应注意源对象不限于是自定义.NET对象。 WPF数据绑定支持.NET对象和XML形式的数据。至提供一些示例,您的绑定源可以是UIElement,任何列表对象,ADO.NET或Web服务对象或XmlNode包含您的XML数据。有关更多信息,请参见Binding sources overview。
在绑定源概述中,您可以了解到INotifyCollectionChanged和INotifyPropertyChange是要实现以支持通知的接口。
对于ADO.NET对象,IBindingList是完成任务的接口。 (这将是其他记录的绑定方法)
对于CLR,您仍然需要实现InotifyCollectionChanged(它们请您参考“为绑定源实现类”一章)]
至于DependencyObject好...他们自己做。