属性绑定到WPF属性会更新,但WPF属性不会改变。

huangapple go评论85阅读模式
英文:

Property bound to WPF property gets updated, but WPF property does not change

问题

我需要让窗口在光标移到其上时更改位置。我已成功创建了一个“MouseEnter”事件触发器,该触发器调用ViewModel中的一个方法。该方法更改了一个名为“RecordingViewTop”的双精度值,该值绑定到XAML文件的“Window.Top”属性。因此,每次触发事件时,它都应该更改窗口的位置,但这并没有自动发生,我不知道为什么。

以下是.XAML文件中的Window.Top属性的当前设置:

Top="{Binding RecordingViewTop, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

以及双精度RecordingViewTop:

private double _recordingViewTop;

public double RecordingViewTop
{
    get { return _recordingViewTop; }
    set
    {
        if (_recordingViewTop != value)
        {
            _recordingViewTop = value;
            OnPropertyChanged();
        }
    }
}

这是我的OnPropertyChanged()实现:

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

我搞不清楚。当我调试我的代码时,我可以看到“RecordingViewTop”确实得到了正确的更新,但是这些更新似乎没有传递到我在Window.Top上进行的绑定。我该如何解决这个问题?

更新:
以下是RecordingViewModel类:

public class RecordingViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private ICommand _moveCommand;
    public ICommand MoveCommand
    {
        get { return _moveCommand ??= new CommandHandler(() => Move(), () => true); }
    }

    private double _recordingViewTop;

    public double RecordingViewTop
    {
        get { return _recordingViewTop; }
        set
        {
            if (_recordingViewTop != value)
            {
                _recordingViewTop = value;
                OnPropertyChanged();
            }
        }
    }
    public RecordingViewModel() { }

    private void Move()
    {
        if (RecordingViewTop == 0)
        {
            _recordingViewTop = SystemParameters.PrimaryScreenHeight - 150;
            MessageBox.Show(RecordingViewTop.ToString());
        }
        else
        {
            _recordingViewTop = 0; 
            MessageBox.Show(RecordingViewTop.ToString());
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

以及如何设置DataContext:

public partial class RecordingView : Window
{
    public RecordingView()
    {
        InitializeComponent();
        RecordingViewModel recordingViewModel = new RecordingViewModel();
        SetViewModel(recordingViewModel);
    }
    public RecordingView SetViewModel(RecordingViewModel recordingViewModel)
    {
        DataContext = recordingViewModel;
        return this;
    }
}

这是我的XAML文件的最新尝试:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseEnter">
        <i:InvokeCommandAction Command="{Binding MoveCommand}"/>
        <i:ChangePropertyAction PropertyName="Top" Value="{Binding RecordingViewTop, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

正如你所看到的,有一个MessageBox,只是为了查看Move()是否被调用,以及RecordingViewTop是否相应地得到更新。如果我将“ChangePropertyAction” Value直接设置为特定值,比如“500”,则窗口在触发事件时会移动。

英文:

I need to make a window change position each time the cursor gets over it. I had no problem creating an event trigger for "MouseEnter" which calls a method in the ViewModel. That method changes a double called "RecordingViewTop", and that double is bound to the "Window.Top" property of the xaml file. So it should change window position each time the event is fired, but that does not happen automatically and I don't know why.

Here's how the Window.Top property currently is in the .XAML file:

Top=&quot;{Binding RecordingViewTop, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;

And the double RecordingViewTop:

        private double _recordingViewTop;

        public double RecordingViewTop
        {
            get { return _recordingViewTop; }
            set
            {
                if (_recordingViewTop != value)
                {
                    _recordingViewTop = value;
                    OnPropertyChanged();
                }
            }
        }

And here's my implementation of OnPropertyChanged():

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

I can't figure it out. When I debug my code, I can see that "RecordingViewTop" does get updated correctly, but somehow that doesn't transfer to the binding I made on Window.Top. How do I fix that?

UPDATE:
Here's the RecordingViewModel class:

public class RecordingViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private ICommand _moveCommand;
    public ICommand MoveCommand
    {
        get { return _moveCommand ??= new CommandHandler(() =&gt; Move(), () =&gt; true); }
    }

    private double _recordingViewTop;

    public double RecordingViewTop
    {
        get { return _recordingViewTop; }
        set
        {
            if (_recordingViewTop != value)
            {
                _recordingViewTop = value;
                OnPropertyChanged();
            }
        }
    }
    public RecordingViewModel() { }

    private void Move()
    {
        if (RecordingViewTop == 0)
        {
            _recordingViewTop = SystemParameters.PrimaryScreenHeight - 150;
            MessageBox.Show(RecordingViewTop.ToString());
        }
        else
        {
            _recordingViewTop = 0; 
            MessageBox.Show(RecordingViewTop.ToString());
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

And here's how DataContext is currently set:

    public partial class RecordingView : Window
{
    public RecordingView()
    {
        InitializeComponent();
        RecordingViewModel recordingViewModel = new RecordingViewModel();
        SetViewModel(recordingViewModel);
    }
    public RecordingView SetViewModel(RecordingViewModel recordingViewModel)
    {
        DataContext = recordingViewModel;
        return this;
    }
}

And this is my latest try for the XAML file:

    &lt;i:Interaction.Triggers&gt;
    &lt;i:EventTrigger EventName=&quot;MouseEnter&quot;&gt;
        &lt;i:InvokeCommandAction Command=&quot;{Binding MoveCommand}&quot;/&gt;
        &lt;i:ChangePropertyAction PropertyName=&quot;Top&quot; Value=&quot;{Binding RecordingViewTop, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;/&gt;
    &lt;/i:EventTrigger&gt;
&lt;/i:Interaction.Triggers&gt;

As you can see, there's a MessageBox just to see if Move() is being called and if RecordingViewTop is getting updated accordingly, and that works fine if I move the mouse over the window, but the window doesn't move at all. Curiously, if I set "ChangePropertyAction" Value directly to a specific value, like "500", the window does move when the event is fired.

答案1

得分: 1

这是代码部分,不需要翻译。

英文:

That's because in the XAML file you are binding the value to the public property "RecordingViewTop", while in the "Move" method you are updating its private var "_recordingViewTop".

Just change your "Move" method to:

private void Move()
{
    if (RecordingViewTop == 0)
    {
        RecordingViewTop = SystemParameters.PrimaryScreenHeight - 150;
        MessageBox.Show(RecordingViewTop.ToString());
    }
    else
    {
        RecordingViewTop = 0; 
        MessageBox.Show(RecordingViewTop.ToString());
    }
}

huangapple
  • 本文由 发表于 2023年7月11日 05:53:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76657561.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定