WPF 绑定指向用户控件

本文关键字:用户 控件 定指 绑定 WPF | 更新日期: 2023-09-27 18:34:47

我有一个包含2 DoubleUpDown的用户控件,我绑定指向该控件

<DoubleUpDown x:Name="X" Grid.Column="1" Grid.Row="0" Value="{Binding Path=Value.X, Mode=TwoWay" />
<DoubleUpDown x:Name="Y" Grid.Column="1" Grid.Row="1" Value="{Binding Path=Value.Y, Mode=TwoWay}" />
当我从外部更改值时,控件

会很好地更新,但是当我更改控件数据时,值保持不变。

我从里面的代码将值绑定到用户控件

Point2DEditorView editor = new Point2DEditorView();
Binding binding = new Binding("Value");
binding.Mode = BindingMode.TwoWay;
editor.SetBinding(Point2DEditorView.ValueProperty, binding);

当我在控件中插入新坐标时,Point2DEditorView.Value也发生了变化。但这不会影响绑定值。

WPF 绑定指向用户控件

Point 是值类型数据。因此,当您将其绑定到控制装箱并发生拆箱时。有关详细信息,请参阅此处。因此,您可以通过创建自己的类(而不是结构体!

class MyPoint
{
    public int X { set; get; }
    public int Y { set; get; }
}

然后将此对象绑定到控件,您将看到所有对象都按预期工作。

更新首先,你的DoubleUpDown在标准FCL中,我认为你的问题在其中。有一个简单的例子,其中所有工作都按预期工作。我为它创建了一个简单的Updown控件:

点类

public class Point2D : INotifyPropertyChanged
{
    private double x;
    private double y;
    public double X
    {
        set
        {
            if (value.Equals(x)) return;
            x = value;
            OnPropertyChanged();
        }
        get { return x; }
    }
    public double Y
    {
        set
        {
            if (value.Equals(y)) return;
            y = value;
            OnPropertyChanged();
        }
        get { return y; }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

上下 xaml

<UserControl x:Name="doubleUpDown" x:Class="PointBind.DoubleUpDown"
         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" 
         mc:Ignorable="d" d:DesignWidth="105" Height="33">
<StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=doubleUpDown}">
    <TextBox Margin="5,5,0,5" Width="50" Text="{Binding Value}" />
    <Button x:Name="Up" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="Up_Click" />
    <Button x:Name="Down" x:FieldModifier="private" Margin="0,5,0,5"  Content="˅" Width="20" Click="Down_Click" />
</StackPanel>
</UserControl>

上下.cs

public partial class DoubleUpDown : UserControl
{
    public double Value
    {
        get { return (double)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(double), typeof(DoubleUpDown), new PropertyMetadata(0.0));

    public DoubleUpDown()
    {
        InitializeComponent();
        DataContext = this;
    }
    private void Up_Click(object sender, RoutedEventArgs e)
    {
        Value++;
    }
    private void Down_Click(object sender, RoutedEventArgs e)
    {
        Value--;
    }

}

Point2DEditorView xaml

<UserControl x:Name="point2DEditorView" x:Class="PointBind.Point2DEditorView"
         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" 
         mc:Ignorable="d" 
         xmlns:local="clr-namespace:PointBind"
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
    <local:DoubleUpDown Value="{Binding Point.X, ElementName=point2DEditorView, Mode=TwoWay}"/>
    <local:DoubleUpDown Value="{Binding Point.Y, ElementName=point2DEditorView, Mode=TwoWay}"/>
</StackPanel>
</UserControl>

上下.cs

    public partial class Point2DEditorView : UserControl
{
    public Point2D Point
    {
        get { return (Point2D)GetValue(PointProperty); }
        set { SetValue(PointProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Point.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PointProperty =
        DependencyProperty.Register("Point", typeof (Point2D), typeof (Point2DEditorView),
            new PropertyMetadata(new Point2D {X = 10, Y = 20}));

    public Point2DEditorView()
    {
        InitializeComponent();
    }
}

测试表单 xaml

<Window x:Class="PointBind.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:PointBind"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <local:Point2DEditorView x:Name="pointEditor"/>
    <Button Content="Button" HorizontalAlignment="Left" Margin="39,121,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>

和测试表格.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        pointEditor.Point = new Point2D{X = 300, Y = 400};
    }
}

希望这有帮助。