2

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

当我需要更改 viewModel 时出现问题。

更改底层 ViewModel 后,在我的 viewModel 对应的 propertyname 上触发 PropertyChanged 事件时,触发 Left 属性的绑定,将窗口移动到正确的 X 位置。但是移动窗口的动作会触发“到源”,设置我的 viewModel 的 Top 属性。 编辑:没有完成“设置”,但未处理 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 框架 3.5 时表现正确,但在 4.0 中却没有。

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

让卢卡伦


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

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

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

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

4

1 回答 1

1

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

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

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

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

Position我发现如果我添加类型的依赖属性并将其直接绑定到SelectedPos而不是将窗口的LeftTop属性绑定到内部的单个 X 和 Y 坐标,则窗口的行为与我期望的一样多SelectedPos。当此依赖属性更改时,我将窗口的和LeftTop设置为.XYPosition

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

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

最后,我删除了主窗口中Left的绑定。Top

于 2012-02-16T23:02:12.093 回答