C# WPF控件派生自标签:自定义属性(带DP)是否未使用setter?
到目前为止,我的所有绑定都工作得很好,只要它们使用了现有的控件属性,比如按钮、标签等等。出于一个目的,我需要一个自定义画布(从画布继承)和一个附加属性。然而,在那里,绑定似乎不起作用。然后,我创建了一个更简单的示例,使用一个自定义标签可以重现我的问题。自定义标签在代码中定义如下:C# WPF控件派生自标签:自定义属性(带DP)是否未使用setter?,c#,wpf,xaml,mvvm,dependency-properties,C#,Wpf,Xaml,Mvvm,Dependency Properties,到目前为止,我的所有绑定都工作得很好,只要它们使用了现有的控件属性,比如按钮、标签等等。出于一个目的,我需要一个自定义画布(从画布继承)和一个附加属性。然而,在那里,绑定似乎不起作用。然后,我创建了一个更简单的示例,使用一个自定义标签可以重现我的问题。自定义标签在代码中定义如下: namespace CustomCanvasTest { class CustomLabel : Label { public string Str { get { return G
namespace CustomCanvasTest
{
class CustomLabel : Label
{
public string Str
{
get { return GetValue(StrProperty) as string; }
set
{
SetValue(StrProperty, value);
}
}
public static readonly DependencyProperty StrProperty =
DependencyProperty.Register("Str", typeof(string), typeof(CustomLabel));
}
}
主窗口的XAML:
<Window x:Class="CustomCanvasTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomCanvasTest"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="313,10,0,0" VerticalAlignment="Top" Width="75" Command="{Binding ButtonClickCmd}"/>
<local:CustomLabel Content="{Binding SomeString}" Str="{Binding SomeString}" HorizontalAlignment="Left" Height="25" Margin="291,288,0,0" VerticalAlignment="Top" Width="176"/>
</Grid>
</Window>
当我点击按钮时,标签内容会发生明显的变化,但是我在setter中为Str
设置的断点永远不会到达。我在这里肯定犯了一些新手的错误,但即使环顾这里关于类似问题的其他答案,我也无法独自找出答案。提前谢谢你的帮助 来自MSDN上的文章:
出于实现的原因,在计算上降低了
将属性标识为依赖项属性并访问该属性
方法来设置它,而不是使用属性
包装器及其设置器。这是因为XAML处理器必须推断
支持代码的整个对象模型仅基于了解
结构所指示的类型和成员关系
标记和各种字符串
因为当前WPF实现的XAML处理器行为
因为属性设置完全绕过包装器,所以不应该
将任何附加逻辑放入包装器的集合定义中
您的自定义依赖项属性。如果你把这样的逻辑放在集合中
定义,则当属性为
在XAML中设置,而不是在代码中设置
因此,你的问题的答案是:不,不一定叫二传手
为了获得有关依赖项属性值更改的通知,您必须通过依赖项属性元数据注册:
public static readonly DependencyProperty StrProperty =
DependencyProperty.Register(
"Str", typeof(string), typeof(CustomLabel),
new PropertyMetadata(StrPropertyChanged));
private static void StrPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var label = obj as CustomLabel;
var str = e.NewValue as string;
...
}
用于获取分配给依赖项属性的值:
为在核心级别确实具有渲染/用户界面影响的非框架属性提供属性元数据
例如:
public class CustomLabel : Label
{
public static readonly DependencyProperty StrProperty =
DependencyProperty.Register("Str",
typeof(string),
typeof(CustomLabel),
new UIPropertyMetadata(String.Empty, IsStrTurn));
public string Str
{
get
{
return GetValue(StrProperty) as string;
}
set
{
SetValue(StrProperty, value);
}
}
private static void IsStrTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
string strOld = e.OldValue as string;
string strNew = e.NewValue as string;
System.Diagnostics.Debug.WriteLine("The old value is " + strOld); // The old value is "init"
System.Diagnostics.Debug.WriteLine("The new value is " + strNew); // The new value is "blub"
}
}
哇,谢谢,这就清楚了!但这让我陷入了一个不利的境地,因为我想在当前设置的属性(这将是一个自定义类,而不是字符串)中订阅一个事件,并且我想在setter中这样做。我无法在构造函数中执行此操作,因为该值可能尚未设置。你对此有什么建议吗?无论如何,非常感谢你的澄清!你可以注册一个。
public class CustomLabel : Label
{
public static readonly DependencyProperty StrProperty =
DependencyProperty.Register("Str",
typeof(string),
typeof(CustomLabel),
new UIPropertyMetadata(String.Empty, IsStrTurn));
public string Str
{
get
{
return GetValue(StrProperty) as string;
}
set
{
SetValue(StrProperty, value);
}
}
private static void IsStrTurn(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
string strOld = e.OldValue as string;
string strNew = e.NewValue as string;
System.Diagnostics.Debug.WriteLine("The old value is " + strOld); // The old value is "init"
System.Diagnostics.Debug.WriteLine("The new value is " + strNew); // The new value is "blub"
}
}