在简单 WPF 中轮换 UX 按预期工作,在 MVVM 中实现时失败



我有一个WPF应用程序中旋转指南针UX元素的工作原型。我有背后的代码和数学来捕获鼠标,并在鼠标向下的情况下旋转指南针,以便北始终跟随鼠标位置。这是一个独立的 UserControl 对象,我在主 Xaml 页面中声明,我在其中插入我需要的各种事件。这篇文章是我如何做背后的代码,这就是我绑定 Angle 属性的方式,这样我就可以让应用逻辑设置值,而无需在控件上进行任何直接输入。

最近,我开始将原型移植到生产存储库中,该存储库被组织成 MVVM 模式。我将简单的单击事件连接到正确的命令,但是UX现在不会旋转,因为它位于新的生产项目中。执行控制台打印显示我的鼠标正在被捕获,并且代码隐藏正在达到我想要应用于 UX 的精确预期角度,但它没有改变。

我已经尝试了几种替代方法,但没有任何方法可以恢复我原来的行为。最初,我尝试在我的视图模型中声明依赖属性,没有更改。我还尝试创建 RotateTransform 并直接设置控件的 RenderTransform,但这会产生非常不稳定的行为(但它确实开始旋转!

连接到 MainViewModel 并设置 TwoWay 绑定是我的 MVVM 项目的新功能,注释掉的行是我在原型中的工作方式绑定的方式。

<Image x:Name="Compass" RenderTransformOrigin="0.5,0.5" >
<Image.DataContext>
<p:MainViewModel/>
</Image.DataContext>
<Image.RenderTransform>
<RotateTransform Angle="{Binding BearingAngle, Mode=TwoWay}"/>
<!--RotateTransform Angle="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type p:CompassView}}, Path=Angle}"/-->
</Image.RenderTransform>
</Image>

该工作背后的代码具有以下依赖项属性。

public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(CompassControl), new UIPropertyMetadata(0.0));
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}

我最接近在 MVVM 项目中获得任何移动时,将变换设置如下(注意,这会导致我的旋转以看似随机的角度闪烁 90-180 度异相,没有任何跟随光标的模式):

this.RenderTransform = new RotateTransform(this.Angle, knobCenter.X, knobCenter.Y);

最终,组织为 MVVM 的生产存储库可能是一个红鲱鱼,我忽略了其他东西,但由于我对 MVVM 应该如何工作相对缺乏经验,这是我唯一表明为什么它在这个项目中不起作用,但在原型演示中很好。

更新:事实证明我的问题与所有这些无关。创建指南针的父控件使用自定义图像类型覆盖 Image 属性(及其 RenderTransform),导致我尝试操作的 RenderTransform 不正确。我将指南针声明为此自定义类型,并删除了父控件中的覆盖代码,一切按预期再次工作。由于此父控件为我的自定义命令执行了所有绑定,而无需直接引用 DataContext 或 ViewModel,因此具有简单绑定足以使所有内容都能从我需要它们的位置相互查看。我相信我从尝试在"简单"应用程序中强制某些绑定的方式与充分利用 ViewModel 自然向下传播控件的方式而获得奇怪的行为。

问题很可能是由于在Image上设置DataContext。 您在那里执行此操作的方式将创建MainViewModel的新实例,这可能不是您想要的。 通常,DataContext设置在WindowUserControl级别,并允许"流动"通过控件。

您很可能需要将DataContext绑定到属性,而不是创建新属性。

如果您要发布更多控件及其主视图模型,我们可以为您提供进一步的帮助。


如果我现在必须猜测,从您当前的代码来看,正确的绑定可能如下所示:

<Image x:Name="Compass" 
RenderTransformOrigin="0.5,0.5" 
DataContext={Binding Path=SomeCompassViewModelPropertyOnYourMainViewModel" >

最新更新