自定义形状的自定义依赖属性的数据绑定不起作用
Data Binding on a custom DependenctProperty of a Cutom Shape doesn't work
我在 .NET 中相对较新,所以,很可能我在做一些愚蠢的事情,但我所做的只是
我用 XAML 创建了一个自定义形状,它基本上是一个圆圈。
Circle.xaml:
<local:Closed2DArea
x:Class="GeoDraw.CustomShapes.Circle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GeoDraw.CustomShapes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Name="circle">
<Path.Data>
<EllipseGeometry Center="{Binding Center, ElementName=circle}" RadiusX="{Binding Radius, ElementName=circle}" RadiusY="{Binding Radius, ElementName=circle}"/>
</Path.Data>
</local:Closed2DArea>
现在,Circle.xaml.cs: 文件有两个 DependencyProperty
:CenterProperty
和 RadiusProperty
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(Circle), null);
public Point Center
{
get => (Point)GetValue(CenterProperty);
set => SetProperty(CenterProperty, value);
}
public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register("Radius", typeof(double), typeof(Circle), null);
public double Radius
{
get => (double)GetValue(RadiusProperty);
set => SetProperty(RadiusProperty, value);
}
这里的SetProperty
方法在实现INotifyPropertyChanged
的基classClosed2DArea
中声明如下:
public abstract class Closed2DArea : Path , INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>( DependencyProperty prop, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
SetValue(prop, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/*constructors and other methods*/
}
当我在具有正常 属性 设置的视图中使用此形状时,一切正常,例如 <CustomShape:Circle Center="20 20" Radius="10">
.
问题::
当我尝试像这样使用数据绑定时出现问题:
<Grid x:Name="maingrid" >
<TextBox x:Name="tbox" Text="80" Margin="258,61,82,189" Width="100" Height="30"/>
<CustomShape:Circle Center="100,80" Radius="{Binding Text, ElementName=tbox}"/>
</Grid>
此处的绑定不起作用,圆从不改变它的半径。我坚持了大约 5 个小时,尝试了很多,但不知道我错过了什么。有什么帮助吗?
您的依赖属性可能需要在设置其内部值时调用的回调方法,例如:
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(Circle), new PropertyMetadata(default(Point), CenterPropertyChanged));
private static void CenterPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var circle = dependencyObject as Circle;
var center = (Point)args.NewValue;
// do something with these values
}
将所有自定义逻辑从 setter 方法移动到此回调方法中 - 数据绑定不会调用您的 setter 方法,而是直接设置依赖项 属性 的值(我想这就是您遇到的情况)。
您不希望将 INotifyPropertyChanged 与依赖属性混合使用。它们是不同的东西。
您应该在 VS 中使用 propdp
快捷方式,而不是更改它使用的 SetValue
功能。
依赖属性将自动与数据绑定一起工作,这就是额外设置所做的。
INotifyPropertyChanged 是为了获得绑定,以便与常规属性一起使用。
我认为你的部分问题是你试图创建一个控件,但使用另一个非 DependencyObject
作为基础。要使用依赖属性,您需要从 DependencyObject 继承。通常,当您根据 UserControl
或 Control
.
创建内容时,您会得到这个
否则,您应该只将常规属性与 INotifyPropertyChanged 一起使用。
我在 .NET 中相对较新,所以,很可能我在做一些愚蠢的事情,但我所做的只是 我用 XAML 创建了一个自定义形状,它基本上是一个圆圈。
Circle.xaml:
<local:Closed2DArea
x:Class="GeoDraw.CustomShapes.Circle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GeoDraw.CustomShapes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Name="circle">
<Path.Data>
<EllipseGeometry Center="{Binding Center, ElementName=circle}" RadiusX="{Binding Radius, ElementName=circle}" RadiusY="{Binding Radius, ElementName=circle}"/>
</Path.Data>
</local:Closed2DArea>
现在,Circle.xaml.cs: 文件有两个 DependencyProperty
:CenterProperty
和 RadiusProperty
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(Circle), null);
public Point Center
{
get => (Point)GetValue(CenterProperty);
set => SetProperty(CenterProperty, value);
}
public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register("Radius", typeof(double), typeof(Circle), null);
public double Radius
{
get => (double)GetValue(RadiusProperty);
set => SetProperty(RadiusProperty, value);
}
这里的SetProperty
方法在实现INotifyPropertyChanged
的基classClosed2DArea
中声明如下:
public abstract class Closed2DArea : Path , INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>( DependencyProperty prop, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
SetValue(prop, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/*constructors and other methods*/
}
当我在具有正常 属性 设置的视图中使用此形状时,一切正常,例如 <CustomShape:Circle Center="20 20" Radius="10">
.
问题::
当我尝试像这样使用数据绑定时出现问题:
<Grid x:Name="maingrid" >
<TextBox x:Name="tbox" Text="80" Margin="258,61,82,189" Width="100" Height="30"/>
<CustomShape:Circle Center="100,80" Radius="{Binding Text, ElementName=tbox}"/>
</Grid>
此处的绑定不起作用,圆从不改变它的半径。我坚持了大约 5 个小时,尝试了很多,但不知道我错过了什么。有什么帮助吗?
您的依赖属性可能需要在设置其内部值时调用的回调方法,例如:
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(Circle), new PropertyMetadata(default(Point), CenterPropertyChanged));
private static void CenterPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var circle = dependencyObject as Circle;
var center = (Point)args.NewValue;
// do something with these values
}
将所有自定义逻辑从 setter 方法移动到此回调方法中 - 数据绑定不会调用您的 setter 方法,而是直接设置依赖项 属性 的值(我想这就是您遇到的情况)。
您不希望将 INotifyPropertyChanged 与依赖属性混合使用。它们是不同的东西。
您应该在 VS 中使用 propdp
快捷方式,而不是更改它使用的 SetValue
功能。
依赖属性将自动与数据绑定一起工作,这就是额外设置所做的。
INotifyPropertyChanged 是为了获得绑定,以便与常规属性一起使用。
我认为你的部分问题是你试图创建一个控件,但使用另一个非 DependencyObject
作为基础。要使用依赖属性,您需要从 DependencyObject 继承。通常,当您根据 UserControl
或 Control
.
否则,您应该只将常规属性与 INotifyPropertyChanged 一起使用。