从 ViewModel C# 访问 GUI 对象的方法

Access GUI object method from ViewModel C#

我正在尝试在图表上创建 "fake" 拖动动画。目标是允许用户通过拖动手动编辑图表中的点。

这个想法很简单:我在图表的顶部放了一个 canvas 并在点击图表的一个点后,一个红色的圆圈在点击的标记值上变得可见,以及 2 条线来自上一个和下一个图形点。我 "just" 必须将每个形状的不透明度设置为 0 到 1 并指定它们的位置(XAML 代码):

<Canvas Name="GraphOverlay" Grid.Row="1">
    <Ellipse Canvas.Left="{Binding ElipseCanvasLeft}" Canvas.Top="{Binding ElipseCanvasTop}" Stroke="{Binding ShapesColor}" StrokeThickness="6" Width="10" Height="10" Opacity="{Binding ShapesOpacity}"/>
    <Line X1="{Binding leftX1}" X2="{Binding leftX2}" Y1="{Binding leftY1}" Y2="{Binding leftY2}" Stroke="{Binding ShapesColor}"  StrokeThickness="3" Opacity="{Binding ShapesOpacity}"/>
    <Line X1="{Binding rightX1}" X2="{Binding rightX2}" Y1="{Binding rightY1}" Y2="{Binding rightY2}" Stroke="{Binding ShapesColor}"  StrokeThickness="3" Opacity="{Binding ShapesOpacity}"/>
</Canvas>

到目前为止,我可以轻松地从我单击的点以及图表上的上一个点和下一个点获取图表值。但是,要定义每个形状在 cavas 上的位置(1 个圆和两条线),我需要将这些图形值转换为实际像素值。对于圆圈,我只需要在用户点击时获取鼠标位置。我正在使用这个:

<i:Interaction.Behaviors>
    <utility:MouseBehaviour MouseX="{Binding PanelX, Mode=OneWayToSource}" MouseY="{Binding PanelY, Mode=OneWayToSource}"/>
</i:Interaction.Behaviors>

和 MouseBehaviour class:

public class MouseBehaviour : System.Windows.Interactivity.Behavior<FrameworkElement>
{
    public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
        "MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

    public double MouseY
    {
        get { return (double)GetValue(MouseYProperty); }
        set { SetValue(MouseYProperty, value); }
    }

    public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
        "MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

    public double MouseX
    {
        get { return (double)GetValue(MouseXProperty); }
        set { SetValue(MouseXProperty, value); }
    }

    protected override void OnAttached()
    {
        AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
    }

    private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
    {
        var pos = mouseEventArgs.GetPosition(AssociatedObject);
        MouseX = pos.X;
        MouseY = pos.Y;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
    }
}

PanelXPanelY 是 ViewModel 的两个属性。

但是我正在努力获取上一个点和下一个点的像素坐标。 On livechart's website,有一个示例展示了如何使用 commandsevents 来访问图形值。但是,在使用事件时,它们可以访问与图表对象关联的 ConvertToPixels 方法。我无法从视图模型访问此方法。

是否有解决方法,或者我应该手动编写该方法吗?

编辑:这是一张图片,显示了我的目标以及我所说的 "next point"、"previous point" 的意思……希望对您有所帮助!

我找到了一个解决方案,我真的不知道这有多难看,但它让我的代码隐藏保持良好和空白。

要访问 UI 元素,您必须先在 XAML 中命名它:

<lvc:CartesianChart Name="Chart" >
...
</lvc:CartesianChart>

然后在您的应用程序中查找它 windows:

var MyChart = App.Current.Windows[0].FindName("Chart") as Chart;

我对 Windows[0] 的硬编码感到不安,但这确实有效。

I found a solution, I don't really know how ugly this is, but it keeps my codebehind nice and blank.

它(非常)丑陋,永远不应该通过代码审查:)

您的视图模型现在不仅依赖于 App class,而且依赖于特定 window 中的特定控件,您的代码必须出现在屏幕上上班。例如,这将永远不会在单元测试中工作,并且会严重破坏 MVVM 模式。

您应该为视图模型注入一个接口,并使用该接口与视图进行交互。如果您有兴趣,可以使用 如何执行此操作的示例。