首页 > 解决方案 > 依赖属性如何在 WPF 中工作?

问题描述

我正在尝试了解依赖属性并学习如何使用它。我正在浏览文章,在这篇文章https://www.c-sharpcorner.com/UploadFile/6d590d/wpf-dependency-property/中有这个例子:

MainWindow.xaml:

<Window x:Class="WpfApplication1.DependencyPropertyDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="DependencyPropertyDemo" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <local:CarDependencyClass x:Key="carDependencyClass"></local:CarDependencyClass>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Label Content="Enter Car:" Grid.Row="0" VerticalAlignment="Center" />
        <TextBox Text="{Binding Path=MyCar, Source={StaticResource carDependencyClass }}" Name="MyTextCar" Height="25" Width="150" />
        <Button Name="MyButton" Content="Click Me!" Height="25" Click="MyButton_Click" Width="150" Grid.Row="1" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;


namespace WpfApplication1 {
    /// <summary>  
    /// Interaction logic for DependencyPropertyDemo.xaml  
    /// </summary>  
    public partial class DependencyPropertyDemo : Window {
        public DependencyPropertyDemo() {
            InitializeComponent();
        }
        private void MyButton_Click(object sender, RoutedEventArgs e) {
            CarDependencyClass dpSample = TryFindResource("carDependencyClass") as CarDependencyClass;
            MessageBox.Show(dpSample.MyCar);
        }
    }
    public class CarDependencyClass : DependencyObject {
        //Register Dependency Property  
        public static readonly DependencyProperty CarDependencyProperty = DependencyProperty.Register("MyProperty", typeof(string), typeof(CarDependencyClass));
        public string MyCar {
            get {
                return (string)GetValue(CarDependencyProperty);
            }
            set {
                SetValue(CarDependencyProperty, value);
            }
        }
    }
}

有用。我注意到他们注册了名为“MyProperty”的依赖属性,并且在程序的任何地方都没有使用它。xaml 中仅使用普通的 CLR 属性 MyCar。

但是还有另一篇文章https://www.c-sharpcorner.com/article/simplest-wpf-dependency-property-for-beginners-on-background-color/。他们还提供了其他示例:

MainWindow.xaml:

<Window x:Class="DependencyPropertyTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:views="clr-namespace:DependencyPropertyTutorial" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DependencyPropertyTutorial" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <SolidColorBrush x:Key="BG" Color="Green" />
    </Window.Resources>
    <Grid>
        <views:CustomButtonControl SetBackground="{DynamicResource BG}"></views:CustomButtonControl>
    </Grid>
</Window>

CustomButtonControl.xaml:

<UserControl x:Class="DependencyPropertyTutorial.CustomButtonControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DependencyPropertyTutorial"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button x:Name="btnCustom" Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Height="52" Click="btnCustom_Click" />
    </Grid>
</UserControl>

CustomButtonControl.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;


namespace DependencyPropertyTutorial {
    /// <summary>  
    /// Interaction logic for CustomButtonControl.xaml  
    /// </summary>  
    public partial class CustomButtonControl : UserControl {
        public CustomButtonControl() {
            InitializeComponent();
        }
        public static readonly DependencyProperty btnDependencyProperty = DependencyProperty.Register("SetBackground", typeof(SolidColorBrush), typeof(CustomButtonControl), new PropertyMetadata(new SolidColorBrush(Colors.HotPink), new PropertyChangedCallback(OnSetColorChanged)));
        public SolidColorBrush SetBackground {
            set {
                SetValue(btnDependencyProperty, value);
            }
            get {
                return (SolidColorBrush)GetValue(btnDependencyProperty);
            }
        }
        private void btnCustom_Click(object sender, RoutedEventArgs e) {
            this.SetBackground = new SolidColorBrush(Colors.IndianRed);
        }
        private static void OnSetColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            CustomButtonControl mycontrol = d as CustomButtonControl;
            mycontrol.callmyInstanceMethod(e);
        }
        private void callmyInstanceMethod(DependencyPropertyChangedEventArgs e) {
            btnCustom.Background = (SolidColorBrush)e.NewValue;
        }
    }
}

在这里,他们使用名称“SetBackground”注册依赖属性,这与 CLR 属性的名称 - SetBackground 完全相同。如果我将依赖属性(我使用 Register 方法注册的那个)“SetBackground”更改为其他属性,例如“SetBackgroundDependencyProperty”,那么在尝试运行应用程序时会出现 XAML 异常。但是“SetBackground”依赖属性甚至没有在任何地方的 xaml 中引用。XAML 中仅在该行引用了 CLR 属性 SetBackground

<views:CustomButtonControl SetBackground="{DynamicResource BG}"></views:CustomButtonControl>

在这个例子中,我在 Visual Studio 中也遇到了一个错误: 在此处输入图像描述

但是当我尝试构建和运行应用程序时,它可以工作。

所以我的问题是:为什么在第一个示例中他们不必将注册的依赖属性命名为与 CLR 属性相同,但在第二个示例中,我必须将注册的依赖属性命名为与 CLR 属性相同。有没有办法将注册的依赖属性命名为与第二个示例中的 CLR 属性不同的名称?考虑到 xaml 仅引用 CLR 属性,为什么以及如何使用依赖属性?我检查了它,根据 VS IntelliSense,在这两个项目中,只有 CLR 属性是从 XAML 中引用的。为什么我必须注册与 CLR 属性同名的依赖属性 - “SetBackground”当在 xaml 中仅引用 CLR 属性并且它从依赖属性返回 SolidColorBrush 时,无论如何:

return (SolidColorBrush)GetValue(btnDependencyProperty);

这是两个示例的解决方案: https ://github.com/KulaGGin/DependencyProperty

标签: wpf

解决方案


第一个例子有点脏,我不会这样编码。有一个很好的约定可以避免混淆 - 将 DP 命名为 CLR 属性 + 'Property'(但这不是强制性的!)并将其注册为 CLR 属性的名称(如果您想在 XAML 中将其用作 DP)。
先回答你的问题:

  • 第一个示例确实有效,因为在任何地方都使用该属性MyCar,它被用作 CLR 属性。如果您尝试绑定到MyCar,它将失败,因为没有这样的依赖属性。要实现此示例中的功能,只需声明一个 CLR 属性就足够了:
    public string MyCar { get; set; }
    而不是与依赖属性混淆。
  • 在第二个示例中,定义了 CLR 属性以及依赖属性SetBackgroundbtnDependencyProperty字段名称不方便,但可以)。您的误解是 XAML 中使用的内容。
    如果您在 XAMLBindingDynamicResource依赖属性以及 CLR 属性中使用是必要的!因此,它们需要具有相同的名称。如果没有,那么您将收到错误消息。
    如果您将属性设置为StaticResource或直接设置为值,甚至不在 XAML 中使用它,那么您将能够运行应用程序。

推荐阅读