Wpf 从两个不同的UserControl绑定两个依赖项属性

Wpf 从两个不同的UserControl绑定两个依赖项属性,wpf,data-binding,user-controls,dependency-properties,Wpf,Data Binding,User Controls,Dependency Properties,我创建了两个单独的用户控件,它们可以一起工作 第一个是一个简单的用户控件,它附加了一个拇指,拇指通过拖动使控件移动,这很简单而且有效 XAML: 第二个用户控件称为直线,它由一个直线控件组成 XAML: 在这里,我尝试在mainwindow.xaml上将它们绑定在一起: <Canvas> <local:ThumbPoint x:Name="ThumbPoint"/> <local:StraightLine StartPosition="{Bindin

我创建了两个单独的用户控件,它们可以一起工作

第一个是一个简单的用户控件,它附加了一个拇指,拇指通过拖动使控件移动,这很简单而且有效

XAML:

第二个用户控件称为直线,它由一个直线控件组成

XAML:

在这里,我尝试在mainwindow.xaml上将它们绑定在一起:

<Canvas>
    <local:ThumbPoint x:Name="ThumbPoint"/>
    <local:StraightLine StartPosition="{Binding Position, ElementName=ThumbPoint}"/>
</Canvas>

理想效果:应更新直线的从属属性起始位置


发生了什么:它没有被更新,所以只有拇指点在移动。

绑定没有为DP使用公共属性包装(
public Point StartPosition
),它直接使用
SetValue()
,因此不会调用setter中的代码

需要的是propertyChangedCallback:

public Point StartPosition
{
    get { return (Point)GetValue(StartPositionProperty); }
    set { SetValue(StartPositionProperty, value); }
}

public static readonly DependencyProperty StartPositionProperty =
    DependencyProperty.Register("StartPosition", typeof(Point), typeof(StraightLine), new PropertyMetadata(new Point(), OnStartPositionChanged));

private static void OnStartPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{
   StraightLine c = (StraightLine) d;
   c.Line.X1 = c.StartPosition.X; 
   c.Line.Y1 = c.StartPosition.Y; 
}
在ThumbPoint
public Point Position
中,属性也有相同的问题,但它在那里工作,因为您直接使用setter:
Position=new Point()

或者以xaml形式绑定X1和Y1值:

<Canvas>
    <Line x:Name="Line" Stroke="Gray" StrokeThickness="1"
          X1="{Binding StartPosition.X, RelativeSource={RelativeSource AncestorType=StraightLine}}"
          Y1="{Binding StartPosition.Y, RelativeSource={RelativeSource AncestorType=StraightLine}}"/>
</Canvas>

(或使用ElementName而不是RelativeSource)

public partial class StraightLine : UserControl
{
    public Point StartPosition
    {
        get { return (Point)GetValue(StartPositionProperty); }
        set { SetValue(StartPositionProperty, value); Line.X1 = value.X; Line.Y1 = value.Y; }
    }

    // Using a DependencyProperty as the backing store for StartPosition.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StartPositionProperty =
        DependencyProperty.Register("StartPosition", typeof(Point), typeof(StraightLine), new PropertyMetadata(new Point()));

    public StraightLine()
    {
        InitializeComponent();

        Line.X1 = 0;
        Line.Y1 = 0;

        Line.X2 = 300;
        Line.Y2 = 200;
    }
}
<Canvas>
    <local:ThumbPoint x:Name="ThumbPoint"/>
    <local:StraightLine StartPosition="{Binding Position, ElementName=ThumbPoint}"/>
</Canvas>
public Point StartPosition
{
    get { return (Point)GetValue(StartPositionProperty); }
    set { SetValue(StartPositionProperty, value); }
}

public static readonly DependencyProperty StartPositionProperty =
    DependencyProperty.Register("StartPosition", typeof(Point), typeof(StraightLine), new PropertyMetadata(new Point(), OnStartPositionChanged));

private static void OnStartPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{
   StraightLine c = (StraightLine) d;
   c.Line.X1 = c.StartPosition.X; 
   c.Line.Y1 = c.StartPosition.Y; 
}
<Canvas>
    <Line x:Name="Line" Stroke="Gray" StrokeThickness="1"
          X1="{Binding StartPosition.X, RelativeSource={RelativeSource AncestorType=StraightLine}}"
          Y1="{Binding StartPosition.Y, RelativeSource={RelativeSource AncestorType=StraightLine}}"/>
</Canvas>