开发者

How do I MVVM-ize this MouseDown code in my WPF 3D app?

In my view, I have:

<UserControl x:Class ... MouseDown="UserControl_MouseDown"> 
    <Viewport3D Name="Viewport" Grid.Column="0">
        ...
    </Viewport3D >
</UserControl>

In my code-behind, I have:

private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
{
    ((MapPanelViewModel)DataContext).OnMouseDown(e, Viewport);
}

And in my view-model, I have:

public void OnMouseDown(MouseEventArgs e, Viewport3D viewport)
{
    var range = new LineRange();
    var isValid = ViewportInfo.Point2DtoPoint3D(viewport, e.GetPosition(viewport), out range);
    if (!isValid)
        MouseCoordinates = "(no data)";
    else
    {
        var point3D = range.PointFromZ(0);
        var point开发者_开发问答 = ViewportInfo.Point3DtoPoint2D(viewport, point3D);
        MouseCoordinates = e.GetPosition(viewport).ToString() + "\n" + point3D + "\n" + point;
    }
}

I really don't have a good sense of how to handle mouse events with MVVM. I always just end up putting them in the code-behind and casting the DataContext as SomeViewModel, then passing the MouseEventArgs on to a handler in my view-model. That's bad enough already, but in this case, I'm actually passing in a control (a Viewport3D), which is necessary for translating coordinates between 2D and 3D.

Any suggestions on how to make this more in tune with MVVM?


I think this is a case of taking MVVM too far. MVVM is not precisely defined, of course, but I think of it in terms of trying to separate my applications high-level mechanics and behaviors from the details of how those mechanics and behaviors get implemented using a particular UI technology (it's just WPF these days, of course, but I find it useful to pretend there might be something else).

Without knowing how your application is supposed to react to the mouse events, it's hard to give specific advice or opinion. Based on what I do see, I think the coordinate translation is best left in the UI layer and then the translated coordinates would get passed to the ViewModel via a method call.


If you are worried about breaking testability by passing a View object through to your ViewModel, create a interface for converting between 3D and 2D points and pass that through instead. In your code behind, you then pass the Viewport3D object through in a wrapper which implements that interface.

Other than that I wouldn't worry about the event handlers in code behind. Use bindings for everything that is easy, use the code behind for the really tricky parts.


I ended up using the MVVM Messenger. So, the mouse event gets handled in the code behind, then it sends a message that the event occurred. Then, my ViewModel can subscribe to this message and receive notification. Works like a charm and keeps everything decoupled.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜