【问题标题】:TwoWay binding on "linked" variables (Top/Left & Height/Width) with .NET 4.0使用 .NET 4.0 对“链接”变量(顶部/左侧和高度/宽度)进行双向绑定
【发布时间】:2012-03-08 07:17:58
【问题描述】:

我在切换到 .NET Framework 4.0 时遇到了一个问题。 我有一个窗口,它在其顶部/左侧和宽度/高度属性上使用双向绑定。

当我需要更改视图模型时出现问题。

更改底层ViewModel后,在我的viewModel对应的propertyname上触发PropertyChanged事件时,触发Left属性的绑定,将窗口移动到正确的X位置。 但是移动窗口的动作会触发“到源”,设置我的 viewModel 的 Top 属性。 EDIT : 没有“设置”完成,但是 Y 绑定没有被处理。

高度和宽度属性的行为相同。

这是一个显示我的问题的小应用程序。

这是模型:

 public class Model : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public Position SelectedPos { get; set; }
        public Position Pos1 { get; set; }
        public Position Pos2 { get; set; }

    public Model( int x, int y, int x2, int y2 )
    {
        Pos1 = new Position( x, y );
        Pos2 = new Position( x2, y2 );
        SelectedPos = Pos1;
    }

    public void Toggle()
    {
        SelectedPos = Pos2;

        if( PropertyChanged != null )
        {
            var e = new PropertyChangedEventArgs( "SelectedPos" );
            PropertyChanged( this, e );
        }
    }
}

public class Position
{
    int _x;
    public int X
    {
        get { return _x; }
        set { _x = value; }
    }

    int _y;
    public int Y
    {
        get { return _y; }
        set { _y = value; }
    }

    public Position( int x, int y )
    {
        X = x;
        Y = y;
    }
}

这是视图:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" 
        Left="{Binding Mode=TwoWay, Path=SelectedPos.X}"
        Top="{Binding Mode=TwoWay, Path=SelectedPos.Y}">
    <Grid>
        <Button Click="Button_Click">Change Position</Button>
    </Grid>
</Window>

最后是代码隐藏:

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        Model model;

        public MainWindow()
        {
            InitializeComponent();
            model = new Model( 5, 5, 500, 500 );
            DataContext = model;
        }

        private void Button_Click( object sender, RoutedEventArgs e )
        {
            model.Toggle();
        }
    }
}

我想知道的是,是否有某种方法可以“冻结”绑定,以防止引擎设置我的 viewModel,直到它处理完我要求它执行的所有绑定。或者在短时间内将绑定从 twoWay 切换到 OneWay。

这里的小应用程序在使用 .NET framework 3.5 时行为正确,但没有 4.0。

我很惊讶我找不到任何人在同样的问题上挣扎,我做错了什么吗? 感谢您的回答,如果有不清楚的地方,请随时询问。

让-卢普·卡伦


我今天早上已经添加了日志(我应该在发布之前就这样做了..),就像你做的那样,你是对的,没有完成“设置”,但是 Y 绑定没有被处理。 当实际切换几次窗口位置时,这种行为更加奇怪。

我将测试您的解决方案,即使我希望避免使用后面的代码(我使用一些代码仅用于测试目的)。

感谢您如此迅速地回答,当我有时间找到无代码隐藏的解决方案时,我会回复您。 由于未设置模型,我可以在触发行为怪异的“位置”绑定之后立即使用 propertychanged 事件分别触发 X 和 Y 绑定。

再次感谢,我走错路了,你为我节省了大量时间。

【问题讨论】:

    标签: wpf binding height width two-way-binding


    【解决方案1】:

    我不确定我是否同意你的观点

    但是移动窗口的动作会触发“到源”,设置我的 viewModel 的 Top 属性。

    我已经运行了您的代码,当您单击“更改位置”按钮时,我可以确认窗口从 (5, 5) 移动到 (500, 5)。但是,我随后添加了另一个按钮,其Click 事件处理程序将窗口的LeftTop 值写入调试日志。我发现这报告说窗口显然在 (500, 500)。然后我将它拖了一小段距离,再次单击此按钮,然后被告知窗口位于 (498, 4)。

    我认为绑定工作正常,但由于某种原因,当其LeftTop 属性都通过绑定快速连续更改时,Windows 不会移动窗口。我不确定为什么会这样;这可能是 .NET 4 中的一个错误,尤其是在 .NET 3.5 中运行时。

    我发现如果我添加 Position 类型的依赖属性并将其直接绑定到 SelectedPos 而不是绑定窗口的 LeftTop 属性,则窗口的行为与我预期的一样到SelectedPos 内的各个 X 和 Y 坐标。当这个依赖属性改变时,我将窗口的LeftTop 值设置为Position 中的XY 值。

    我添加的依赖属性和属性改变回调如下:

        public Position WindowPosition
        {
            get { return (Position)GetValue(WindowPositionProperty); }
            set { SetValue(WindowPositionProperty, value); }
        }
    
        public static readonly DependencyProperty WindowPositionProperty =
            DependencyProperty.Register("WindowPosition", typeof(Position), typeof(MainWindow), new PropertyMetadata(WindowPosition_Changed));
    
        private static void WindowPosition_Changed(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var mainWindow = obj as MainWindow;
            mainWindow.Left = mainWindow.WindowPosition.X;
            mainWindow.Top = mainWindow.WindowPosition.Y;
        }
    

    我发现绑定必须在代码隐藏中进行。我将这一行添加到MainWindow 构造函数中:

            SetBinding(WindowPositionProperty, new Binding("SelectedPos"));
    

    最后,我在主窗口中删除了LeftTop 上的绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 2016-12-17
      • 2019-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多