“链接”上的双向绑定变量(顶部/左侧和高度/宽度)与.NET 4.0

发布于 2025-01-06 13:29:58 字数 2851 浏览 2 评论 0原文

我在切换到 .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 Framework 3.5 时行为正确,但不正确 与4.0。

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

Jean-Loup Kahloun


我今天早上添加了日志(我应该在在这里发帖之前完成该操作..),就像您所做的那样,您是对的,没有完成“设置”,但 Y 绑定未处理。 当实际多次切换窗口位置时,行为更加奇怪。

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

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

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

I have encounted a problem when switching to the .NET Framework 4.0.
I have a window that uses twoway binding on its Top/Left & Widht/Height properties.

A problem occurs when i need to change the viewModel.

After changing the underlying ViewModel, when triggering the PropertyChanged event on the propertyname corresponding to my viewModel, the Left property's binding is triggered, moving the window to the correct X-location.
But the action of moving the window triggers a "to source", setting my viewModel's Top property.
EDIT : There is not "set" done, but the Y Binding is not processed.

Same behavior with the Height & Width properties.

Here is a tiny application that shows my problem.

here is the model :

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

And here is the view :

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

And finally the code-behind :

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

What I would've liked to know is if there is some kind a way to "freeze" a binding, to prevent the engine from setting my viewModel until it has finished processing all the binding I asked it to do. or to switch the binding from twoWay to OneWay, for a short period of time.

The small application here behaves correctly when using the .NET framework 3.5 but doesn't
with the 4.0.

I am surprised I couldn't find anyone struggling with the same issue, am i doing something wrong ?
I thank you for your answers, don't hesitate to ask if something is not clear.

Jean-Loup Kahloun


I've added logs this morning (i should've done that before posting here..), just like you did, and you are right, there is no "set" done, but the Y binding is not processed.
The behavior is even more strange when actually toggling several times the position of the window.

I'm going to test your solution, even though I would have liked to avoid using code behind ( I used some for test purposes only ).

I thank you for answering so fast, i'll get back at you when I have some time to find a code-behind-free solution.
As the model is not set, i may be able to trigger seperately the X and Y bindings with propertychanged events, right after the weird-behaving "Position" binding is triggered.

Thanks again, i was going the wrong way, you saved me loads of time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一杯敬自由 2025-01-13 13:29:58

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

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

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

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

我发现,如果我添加 Position 类型的依赖属性并将其直接绑定到 SelectedPos 而不是绑定窗口的 <将 code>Left 和 Top 属性设置为 SelectedPos 内的各个 X 和 Y 坐标。当此依赖属性更改时,我将窗口的 LeftTop 值设置为 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 上的绑定。

I'm not sure I agree with your point

But the action of moving the window triggers a "to source", setting my viewModel's Top property.

I have run your code and I can confirm that the window moves from (5, 5) to (500, 5) when you click the 'Change Position' button. However, I then added another button whose Click event handler wrote the values of the window's Left and Top values to the debug log. I found that this reported that the window was apparently at (500, 500). I then dragged it a short distance, clicked this button again and was then informed that the window was at (498, 4).

I think the bindings are working correctly, but for some reason, Windows doesn't move the window when its Left and Top properties both change via bindings in quick succession. I'm not sure why this happens; it could be a bug in .NET 4, especially if it worked in .NET 3.5.

I found that the window behaved a bit more as I would expect it to if I added a dependency property of type Position and bound that direct to SelectedPos rather than binding the window's Left and Top properties to the individual X and Y coordinates inside SelectedPos. When this dependency property changed, I set the window's Left and Top values to the X and Y values within the Position.

The dependency property and property-changed callback I added was as follows:

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

I found that the binding had to be made in code-behind. I added this line to the MainWindow constructor:

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

Finally, I deleted the bindings on Left and Top in the main window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文