【问题标题】:WPF bind point to UserControlWPF 绑定点到 UserControl
【发布时间】:2013-10-11 06:07:36
【问题描述】:

我有一个包含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 也发生了变化。但这并不影响绑定值。

【问题讨论】:

    标签: c# wpf binding user-controls


    【解决方案1】:

    Point 是一个值类型的数据。因此,当您将其绑定到控制装箱和拆箱时,就会发生这种情况。有关详细信息,请参阅this。因此,您可以通过创建自己的类(而不是结构!)来轻松解决这个问题:

    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));
        }
    }
    

    UpDown 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>
    

    UpDown .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>
    

    UpDown .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};
        }
    }
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的快速响应。 Point2D 已经是类。我唯一能做的就是在每个数值控制值更改事件上创建新值 Value = new Point2D(xcontrol.Value, ycontorl.Value);它有帮助。
    • 你使用什么库?我在标准库中找不到 Point2D。
    • 这是我自己的课。代表一个点(不要问我为什么要写另一个点类:()。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多