Wpf 将中心缩放到鼠标位置图像

Wpf 将中心缩放到鼠标位置图像,wpf,image,zooming,reactiveui,Wpf,Image,Zooming,Reactiveui,我一直在关注投票率最高的答案。 (带有zoomorder.cs的一个) 如果我把它加入到我的项目中,一切都很好。然而,我的项目是一个ReactiveUI应用程序,我正在努力使用ReactiveUI设计模式复制该代码 到目前为止我所做的: 创建了一个新的UserControl <UserControl x:Class="ImageViewer.Controls.ZoomControl" xmlns="http://schemas.microsoft.com/winf

我一直在关注投票率最高的答案。 (带有zoomorder.cs的一个)

如果我把它加入到我的项目中,一切都很好。然而,我的项目是一个ReactiveUI应用程序,我正在努力使用ReactiveUI设计模式复制该代码

到目前为止我所做的:

创建了一个新的UserControl

<UserControl x:Class="ImageViewer.Controls.ZoomControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ImageViewer.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Border BorderThickness="10" BorderBrush="Red">
        <Image x:Name="RenderingImage" RenderTransformOrigin="0,0" Stretch="None" Source="{Binding}" ClipToBounds="True">
            <Image.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform x:Name="ImageScale" ScaleX="{Binding}" ScaleY="{Binding}"/>
                    <TranslateTransform x:Name="ImageTranslate" X="{Binding}" Y="{Binding}" />
                </TransformGroup>
            </Image.LayoutTransform>
        </Image>
    </Border>
</UserControl>

添加了视图->视图模型之间的绑定

 public partial class ZoomControl : IViewFor<ZoomControlViewModel>
    {
        public static readonly DependencyProperty ViewModelProperty = DependencyProperty
       .Register(nameof(ViewModel), typeof(ZoomControlViewModel), typeof(ZoomControl), null);
        public ZoomControl()
        {
            InitializeComponent();

            this.DataContextChanged += (sender, args) => ViewModel = DataContext as ZoomControlViewModel;

            this.WhenActivated(cleanup =>
            {
                this.OneWayBind(ViewModel, vm => vm.ImageSource, v => v.RenderingImage.Source).DisposeWith(cleanup);

                this.OneWayBind(ViewModel, vm => vm.ScaleX, v => v.ImageScale.ScaleX).DisposeWith(cleanup);
                this.OneWayBind(ViewModel, vm => vm.ScaleY, v => v.ImageScale.ScaleY).DisposeWith(cleanup);
                this.OneWayBind(ViewModel, vm => vm.TranslateX, v => v.ImageTranslate.X).DisposeWith(cleanup);
                this.OneWayBind(ViewModel, vm => vm.TranslateY, v => v.ImageTranslate.Y).DisposeWith(cleanup);

                RenderingImage.Events().MouseWheel.Select(e => new Tuple<int, Point>(e.Delta, e.GetPosition(RenderingImage))).InvokeCommand(ViewModel.ZoomAction).DisposeWith(cleanup);
            });
        }

        public ZoomControlViewModel ViewModel { get => (ZoomControlViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); }
        object IViewFor.ViewModel { get => ViewModel; set => ViewModel = (ZoomControlViewModel)value; }
    }
公共部分类ZoomControl:IViewFor
{
公共静态只读DependencyProperty ViewModelProperty=DependencyProperty
.Register(nameof(ViewModel)、typeof(ZoomControlViewModel)、typeof(ZoomControl)、null);
公共动物控制
{
初始化组件();
this.DataContextChanged+=(发送方,参数)=>ViewModel=DataContext作为ZoomControl ViewModel;
当激活时(清除=>
{
this.OneWayBind(ViewModel,vm=>vm.ImageSource,v=>v.RenderingImage.Source);
这个.OneWayBind(ViewModel,vm=>vm.ScaleX,v=>v.ImageScale.ScaleX);
这个.OneWayBind(ViewModel,vm=>vm.ScaleY,v=>v.ImageScale.ScaleY);
这个.OneWayBind(ViewModel,vm=>vm.TranslateX,v=>v.ImageTranslate.X);
这个.OneWayBind(ViewModel,vm=>vm.TranslateY,v=>v.ImageTranslate.Y);
RenderingImage.Events().mouseweel.Select(e=>newtuple(e.Delta,e.GetPosition(RenderingImage))).InvokeCommand(ViewModel.ZoomAction).DisposeWith(cleanup);
});
}
公共ZoomControlViewModel视图模型{get=>(ZoomControlViewModel)GetValue(ViewModelProperty);set=>SetValue(ViewModelProperty,value);}
object IViewFor.ViewModel{get=>ViewModel;set=>ViewModel=(ZoomControlViewModel)值;}
}
在视图模型中,我实现了如下缩放命令

 public ZoomControlViewModel()
        {
            ZoomAction = ReactiveCommand.Create<Tuple<int, Point>>(z => Zoom(z));
        }

private void Zoom(Tuple<int, Point> deltaArgs)
        {
            int delta = deltaArgs.Item1;
            Point relativePosition = deltaArgs.Item2;

            //var ScaleTransform = GetScaleTransform();
            //var TranslateTransform = GetTranslateTransform();

            double zoom = delta > 0 ? .2 : -.2;
            if (!(delta > 0) && (ScaleX < .4 || ScaleY < .4))
                return;

            double absoluteX;
            double absoluteY;

            absoluteX = relativePosition.X * ScaleX + TranslateX;
            absoluteY = relativePosition.Y * ScaleY + TranslateY;

            ScaleX += zoom;
            ScaleY += zoom;

            TranslateX = absoluteX - relativePosition.X * ScaleX;
            TranslateY = absoluteY - relativePosition.Y * ScaleY;
        }
公共ZoomControl视图模型() { ZoomAction=ReactiveCommand.Create(z=>Zoom(z)); } 专用空心缩放(元组三角形) { int delta=deltaArgs.Item1; 点相对位置=deltaArgs.Item2; //var ScaleTransform=GetScaleTransform(); //var TranslateTransform=GetTranslateTransform(); 双变焦=增量>0?.2:-.2; 如果(!(增量>0)和(&(ScaleX<.4 | | ScaleY<.4)) 返回; 双重绝对; 双重绝对; 绝对X=相对位置X*ScaleX+TranslateX; 绝对=相对位置Y*ScaleY+TranslateY; ScaleX+=缩放; 缩放+=缩放; TranslateX=绝对X-相对位置X*ScaleX; TranslateY=绝对-相对位置。Y*ScaleY; } 现在我的问题。对于上面的示例,缩放效果很好,但它不会缩放到鼠标位置,而是缩放到图像的左上角

据我所知(这可能是问题所在),更改图像的TranslateTransformTranslateXTranslateY)应该可以将我缩放到当前鼠标位置


任何提示都将不胜感激

ScaleTransform
具有定义中心点坐标的
CenterX
CenterY
属性。这与ReactiveUI有什么关系?@mm8它们之间没有任何关系。我没有接触过CenterX和CenterY,我没有看到它们在作为示例的示例中使用,但我不想从中心缩放,我想从当前鼠标位置缩放。触发我的是,我使用了完全相同的代码,只使其反应,似乎TranslateX/TranslateY确实发生了变化,但在图像上它没有变化。感觉绑定被忽略了。有时警告消息可以为您提供有关rxui绑定问题的更多信息。发现问题的原因不是rxui绑定,而是TranslateTransform是不可变的。因此,绑定可以工作,但由于TranslateTransform的不变性,更新没有完成。