0

我试图了解通知如何适用于 WPF 中的附加属性。

例如,考虑 ScrollViewer.CanContentScrollProperty 属性。

假设我们有以下 ListBox

<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是如何接收到connected属性的值发生变化的信息就不清楚了。可以假设通过函数 FrameworkPropertyMetadata (PropertyChangedCallback propertyChangedCallback) ,但事实是属性 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 属性已更改?

4

2 回答 2

-1

在调用堆栈上,我们可以假设属性值的更改通过某种 XAML 触发器捕获并分配给 ScrollContentPresenter.CanContentScrollProperty 属性

在此处输入图像描述

于 2020-05-11T12:35:00.103 回答
-1

不幸的是,我上次玩 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 绑定),必须实现合适的属性更改通知机制,例如 INotifyPropertyChanged。有关 INotifyPropertyChanged 实现的示例,请参见如何:实现属性更改通知。

然后你可以找到:

虽然图中未显示,但应注意绑定源对象不限于为自定义 .NET 对象。WPF 数据绑定支持 .NET 对象和 XML 形式的数据。为了提供一些示例,您的绑定源可以是 UIElement、任何列表对象、ADO.NET 或 Web 服务对象,或者包含您的 XML 数据的 XmlNode。有关详细信息,请参阅绑定源概述

在 Binding 源概述中,您可以看到 INotifyCollectionChanged 和 INotifyPropertyChange 是要实现以支持通知的接口。

对于 ADO.NET 对象,IBindingList 是完成这项工作的接口。(这将是另一种记录在案的绑定方法)

对于 CLR,您仍然需要实现 INotifyCollectionChanged(他们让您参考“为绑定源章节实现类”)

至于 DependencyObject 好……他们自己做。

于 2020-05-11T01:41:22.293 回答