【问题标题】:wpf usercontrol positioning not updating instantly while the bound TextBox doeswpf usercontrol定位不会在绑定的TextBox时立即更新
【发布时间】:2012-07-03 14:28:04
【问题描述】:

我在用户控件 (InfoControl) 中有 2 个文本框,绑定到实现 INotifyPropertyChanged 的​​ VM 中的 Point 属性。

我有另一个包含可拖动矩形的 UserControl (DesignerControl)。 Rectangle 的 Canvas.Left 和 Canvas.Bottom 绑定到同一 VM 的 ConvPoint 属性。 ConvPoint 属性 (0 => ActualWidth) 是 Point 属性 (0 => 1) 的转换版本

当我拖动我的矩形时,ConvPoint VM 属性和文本框中的值会立即更新,但是当我用新值更新我的文本框时,VM Point 属性会立即更新,但矩形仅在我拖动时定位再次矩形,而不是立即矩形。

一段代码解释一下:

首先,我的 ViewModel 的 Position 属性

public class MyVM : ViewModelBase
{
    private DependencyPoint position;
    public DependencyPoint Position
    {
        get { return this.position; }
        set
        {
            this.position = value;
            RaisePropertyChanged("Position");
        }
    }

    public DependencyPoint ConvPosition
    {
        get { return new Point(this.Position.X * MainVM.ActualWidth, this.Position.Y * MainVM.AcutalHeight);}
        set
        {
            Point p = new Point(value.X/MainVM.ActualWidth,value.Y/MainVM.ActualHeight);
            this.position = p;
            RaisePropertyChanged("ConvPosition");
        }
    }
}


编辑: 我使用这个类 DependencyPoint 来通知 X 和 Y 属性:

public class DependencyPoint : DependencyObject
{

    public enum PointOrder
    {
        isStartPoint,
        isEndPoint,
        isPoint1,
        isPoint2
    }

    public DependencyPoint()
    {
    }

    public DependencyPoint(Double x, Double y, PointOrder po)
    {
        this.X = x;
        this.Y = y;
        this.Order = po;
    }

    public DependencyPoint(DependencyPoint point)
    {
        this.X = point.X;
        this.Y = point.Y;
        this.Order = point.Order;
    }


    public DependencyPoint(Point point, PointOrder po)
    {
        this.X = point.X;
        this.Y = point.Y;
        this.Order = po;
    }

    public Point ToPoint()
    {
        return new Point(this.X, this.Y);
    }



    public PointOrder Order
    {
        get { return (PointOrder)GetValue(OrderProperty); }
        set { SetValue(OrderProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Order.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty OrderProperty =
        DependencyProperty.Register("Order", typeof(PointOrder), typeof(DependencyPoint), new UIPropertyMetadata(null));



    public Double X
    {
        get { return (Double)GetValue(XProperty); }
        set { SetValue(XProperty, value); }
    }

    // Using a DependencyProperty as the backing store for X.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty XProperty =
        DependencyProperty.Register("X", typeof(Double), typeof(DependencyPoint), new UIPropertyMetadata((double)0.0));



    public Double Y
    {
        get { return (Double)GetValue(YProperty); }
        set { SetValue(YProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Y.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty YProperty =
        DependencyProperty.Register("Y", typeof(Double), typeof(DependencyPoint), new UIPropertyMetadata((double)0.0));
}


然后在我的信息控制中:

<Grid Grid.Row="0" DataContext="{Binding Position}">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <DockPanel Margin="3,3,0,1" Grid.Row="0" LastChildFill="True">
                    <TextBlock Foreground="White" Padding="0,3,0,0" Margin="2,0,0,0" DockPanel.Dock="Left" Text="StartPoint.X :"/>
                    <TextBox FontWeight="DemiBold" Foreground="Black" Background="#efefef" Width="Auto" Margin="7,0,0,0" Text="{Binding X, Converter={StaticResource StDConverter}, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
                </DockPanel>
                <DockPanel Margin="3,3,0,1" Grid.Row="1" LastChildFill="True">
                    <TextBlock Foreground="White" Padding="0,3,0,0" Margin="2,0,0,0" DockPanel.Dock="Left" Text="StartPoint.Y :"/>
                    <TextBox FontWeight="DemiBold" Foreground="Black" Background="#efefef" Width="Auto" Margin="7,0,0,0" Text="{Binding Y, Converter={StaticResource StDConverter}, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
                </DockPanel>
            </Grid>

在 DesignerControl 中:

<UserControl>
    <Canvas>
        <Rectangle x:Name="Point" Width="10" Height="10" Canvas.Bottom="{Binding ConvPosition.Y, Mode=TwoWay}" Canvas.Left="{Binding ConvPosition.X, Mode=TwoWay}" />
    </Canvas>
</UserControl>

我可以访问 actualWidth 并且我的 Rectangle 在 Canvas 中的位置很好。

我知道我在 VM 中的属性或有点脏,但我不知道其他方法可以正确执行此操作并管理转换。

有什么想法吗?

【问题讨论】:

    标签: wpf binding textbox viewmodel


    【解决方案1】:

    因为 ConvPosition 取决于 Position,您应该在 Position setter 中为 ConvPosition 提出 NotificationChanged。

    public Point Position
    {
        get { return this.position; }
        set
        {
            this.position = value;
            RaisePropertyChanged("Position");
            RaisePropertyChanged("ConvPosition");
        }
    }
    

    ConvPosition 你可以改成这个

    public Point ConvPosition
    {
        get { return new Point(this.Position.X * MainVM.ActualWidth, this.Position.Y * MainVM.AcutalHeight); }
        set
        {
            this.Position = new Point(value.X/MainVM.ActualWidth, value.Y/MainVM.ActualHeight);
        }
    }
    

    编辑

    我认为 MyVM 中的两个附加属性将是最简单的解决方案。

    public double X
    {
        get { return Position.X; }
        set
        {
            Position = new Point(value, Position.Y);
            RaisePropertyChanged("X");
        }
    }
    
    public double Y
    {
        get { return Position.Y; }
        set
        {
            Position = new Point(Position.X, value);
            RaisePropertyChanged("Y");
        }
    }
    

    仅在 Grid 中更改:

    <Grid DataContext="{Binding}">
    

    【讨论】:

    • aarh 这个答案似乎很完美,但不幸的是,它不起作用。我现在很迷茫......
    • 我认为最后一个问题是:Point 是一个结构。它没有实现 INotifyPropertyChanged。使用一个(自己的)类,该类在您的类MyVM 中创建或可能创建另外两个属性XY,为每次更改创建一个新的点位置。将文本框绑定到这些。
    • 我已经尝试了实现 INotifyPRpertyChanged 的​​类,这是我的 DependencyPoint 类,因为我确实无法传播我的积分值。这就是我被困在这里的原因(对不起,我已经有一段时间没有被困在这里了,我忘了提)
    • 您已尝试将Point Position 替换为DependencyPoint Position,但它不起作用?你能展示你的 DependencyPoint 类吗?
    • 我的错,它是一个 DependencyPoint,我复制/粘贴错误,我将编辑我的帖子并添加 DependencyPoint 类
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 2011-01-14
    • 2013-06-15
    相关资源
    最近更新 更多