wpf - 依赖属性如何在 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
解决方案
第一个例子有点脏,我不会这样编码。有一个很好的约定可以避免混淆 - 将 DP 命名为 CLR 属性 + 'Property'(但这不是强制性的!)并将其注册为 CLR 属性的名称(如果您想在 XAML 中将其用作 DP)。
先回答你的问题:
- 第一个示例确实有效,因为在任何地方都使用该属性
MyCar
,它被用作 CLR 属性。如果您尝试绑定到MyCar
,它将失败,因为没有这样的依赖属性。要实现此示例中的功能,只需声明一个 CLR 属性就足够了:
public string MyCar { get; set; }
而不是与依赖属性混淆。 - 在第二个示例中,定义了 CLR 属性以及依赖属性
SetBackground
(btnDependencyProperty
字段名称不方便,但可以)。您的误解是 XAML 中使用的内容。
如果您在 XAMLBinding
或DynamicResource
依赖属性以及 CLR 属性中使用是必要的!因此,它们需要具有相同的名称。如果没有,那么您将收到错误消息。
如果您将属性设置为StaticResource
或直接设置为值,甚至不在 XAML 中使用它,那么您将能够运行应用程序。
推荐阅读
- pentaho - 如何在 pentaho 报表设计器的值字段中添加 $ 符号
- java - 如何使用 List<> 从 Java 调用 kotlin 函数
- javascript - 将脚本添加到 vue 模板内部
- lua - ComputerCraft 跟踪 Lua “io” 库异常
- video - 如何将三个 ffmpeg 命令合二为一?
- r - 如何处理fluidrow rshiny内部的空间
- angularjs - 从谷歌驱动器获取文件并通过 HTML5 输入标签显示在我的网页上
- beaker - 使用 Beakerx 自定义魔法
- ios - iOS 应用背景为黑色,应用图标溢出到边缘
- asp.net-mvc - 配置错误 Azure Key Vault 作为 Visual Studio 连接服务 ConfigurationBuilder