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

C# 从ViewModel C访问GUI对象方法,c#,wpf,mvvm,viewmodel,C#,Wpf,Mvvm,Viewmodel,我试图在图表上创建一个假拖动动画。目标是允许用户通过拖动图形手动编辑点 这个想法相当简单:我将画布放在图形的顶部,单击图形的一个点时,在单击的标记值上会出现一个红色圆圈,以及来自上一个和下一个图形点的两条线。我只需将每个形状的不透明度从0设置为1,并指定它们的位置XAML代码: <Canvas Name="GraphOverlay" Grid.Row="1"> <Ellipse Canvas.Left="{Binding ElipseCanvasLeft}" Canva

我试图在图表上创建一个假拖动动画。目标是允许用户通过拖动图形手动编辑点

这个想法相当简单:我将画布放在图形的顶部,单击图形的一个点时,在单击的标记值上会出现一个红色圆圈,以及来自上一个和下一个图形点的两条线。我只需将每个形状的不透明度从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>
还有鼠标行为类:

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;
    }
}
和PanelX和PanelY是ViewModel中的两个属性

但是,我正在努力获取上一点和下一点的像素坐标,有一个示例演示了如何使用命令和事件访问图形值。但是,在使用事件时,它们可以访问与图表对象关联的ConvertToPixels方法。我无法从viewmodel访问此方法

有没有办法解决这个问题,或者我应该手动编写这个方法

编辑:这里有一张图片显示了我的目标,以及我所说的下一点、上一点的意思。。。希望能有帮助


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

要访问该UI元素,必须在XAML中将其命名为:

<lvc:CartesianChart Name="Chart" >
...
</lvc:CartesianChart>
我对Windows[0]的硬编码并不感到安心,但这确实起到了作用


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

它非常难看,不应该通过代码审查:

现在,视图模型不仅依赖于应用程序类,而且依赖于特定窗口中的特定控件,该窗口必须显示在屏幕上,代码才能正常工作。例如,这在单元测试中永远不起作用,严重破坏了MVVM模式


您应该向视图模型注入一个接口,并使用该接口与视图交互。如果您感兴趣,可以提供一个示例来说明如何执行此操作。

这非常难看,因为您的视图模型现在不仅依赖于应用程序,而且依赖于屏幕上必须显示的特定窗口中的特定控件……这在单元测试中永远不会起作用。非常感谢您的回答!我已经实现了它,它就像一个符咒。这将是非常有用的知道!Tbh此代码永远不会在单元测试中审查或使用。即使是MVVM模式也是一种过分的杀伤力。然而,我讨厌制作蹩脚的作品,我喜欢学习,所以非常感谢您的反馈
var MyChart = App.Current.Windows[0].FindName("Chart") as Chart;