You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Avalonia 11中遵循MVVM从ViewModel触发PanAndZoom的ResetMatrix操作

在Avalonia 11中遵循MVVM原则触发PanAndZoom控件的ResetMatrix操作

问题背景

我在Avalonia 11应用中使用PanAndZoom控件,该控件的缩放重置只能通过控件方法触发。我想直接从ViewModel触发ResetMatrix操作以遵循MVVM原则,当前我在视图的代码后台中调用该方法:

public partial class VideoView : UserControl
{
    #region Public Constructors

    public VideoView()
    {
        InitializeComponent();

        var zoomBorder = this.FindControl<ZoomBorder>("VideoBorder");
        var dataContext = this.DataContext as VideoViewModel;

        if (dataContext != default
            && zoomBorder != default)
        {
            dataContext.OnVideoCentredEvent += (s, e) => zoomBorder.ResetMatrix();
        }
    }

    #endregion Public Constructors
}

我尝试过相关StackOverflow答案,但无法适配Avalonia 11的可用依赖属性,希望找到基于Behavior或其他可行的解决方案。


解决方案

方法一:使用自定义Behavior实现

通过Avalonia Behaviors可以实现ViewModel与控件的解耦,无需在后台代码中直接绑定事件。

  1. 安装依赖
    确保项目引用Avalonia.Xaml.Behaviors NuGet包(适配Avalonia 11版本)。

  2. 编写自定义Behavior

using Avalonia;
using Avalonia.Controls;
using Avalonia.Xaml.Interactivity;
using PanAndZoom; // 替换为你的PanAndZoom控件命名空间

public class ZoomBorderResetBehavior : Behavior<ZoomBorder>
{
    // 定义可绑定属性,ViewModel设置为true时触发重置
    public static readonly StyledProperty<bool> ResetRequestedProperty =
        AvaloniaProperty.Register<ZoomBorderResetBehavior, bool>(
            nameof(ResetRequested), 
            defaultBindingMode: BindingMode.TwoWay);

    public bool ResetRequested
    {
        get => GetValue(ResetRequestedProperty);
        set => SetValue(ResetRequestedProperty, value);
    }

    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        
        if (e.Property == ResetRequestedProperty && (bool)e.NewValue)
        {
            AssociatedObject?.ResetMatrix();
            // 重置属性避免重复触发
            ResetRequested = false;
        }
    }
}
  1. ViewModel中添加对应属性
private bool _resetRequested;
public bool ResetRequested
{
    get => _resetRequested;
    set => SetProperty(ref _resetRequested, value); // 需实现INotifyPropertyChanged
}

// 触发重置的命令(比如绑定到按钮)
public ICommand ResetZoomCommand => new RelayCommand(() =>
{
    ResetRequested = true;
});
  1. XAML中绑定Behavior
<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Behaviors"
             xmlns:local="clr-namespace:YourAppNamespace"
             xmlns:pan="clr-namespace:PanAndZoom;assembly=PanAndZoom">

    <pan:ZoomBorder x:Name="VideoBorder">
        <i:Interaction.Behaviors>
            <local:ZoomBorderResetBehavior ResetRequested="{Binding ResetRequested}" />
        </i:Interaction.Behaviors>
        <!-- 你的视频内容 -->
    </pan:ZoomBorder>
</UserControl>

方法二:使用附加属性实现

通过附加属性可以直接在XAML中绑定ViewModel属性,无需引入Behavior库。

  1. 编写附加属性
using Avalonia;
using Avalonia.Controls;
using PanAndZoom;

public static class ZoomBorderExtensions
{
    public static readonly AttachedProperty<bool> ResetMatrixProperty =
        AvaloniaProperty.RegisterAttached<ZoomBorderExtensions, ZoomBorder, bool>(
            "ResetMatrix", 
            defaultBindingMode: BindingMode.TwoWay);

    public static bool GetResetMatrix(ZoomBorder element)
    {
        return element.GetValue(ResetMatrixProperty);
    }

    public static void SetResetMatrix(ZoomBorder element, bool value)
    {
        element.SetValue(ResetMatrixProperty, value);
    }

    static ZoomBorderExtensions()
    {
        ResetMatrixProperty.Changed.Subscribe(args =>
        {
            if (args.Sender is ZoomBorder zoomBorder && (bool)args.NewValue)
            {
                zoomBorder.ResetMatrix();
                // 重置属性避免重复触发
                SetResetMatrix(zoomBorder, false);
            }
        });
    }
}
  1. XAML中绑定附加属性
<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:YourAppNamespace"
             xmlns:pan="clr-namespace:PanAndZoom;assembly=PanAndZoom">

    <pan:ZoomBorder x:Name="VideoBorder"
                    local:ZoomBorderExtensions.ResetMatrix="{Binding ResetRequested}">
        <!-- 你的视频内容 -->
    </pan:ZoomBorder>
</UserControl>

内容的提问来源于stack exchange,提问作者budul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:43:16