简体   繁体   中英

Constructing images in C# WPF/MVVM (drawing lines, arcs, text)

In a WPF standalone-application I need to draw an image based on a series of 'commands' such as "text a at position x,y" and "draw line from x1,y1 to x2,y2".

My problems and considerations are outlined below - any help and comments are most appreciated!

  • The image is of a water pump constructed by our company.

  • The commands are generated by a proprietory system within our company.

  • There are no problems interpreting the commands.

  • My issue is with

    a) what WPF control should I choose to draw it 'on' ?

    b) how can I move the major part of the code to unit-testable classes?

    a1) I have tried with PathGeometry, which is excellent for drawing geometric shapes but can't draw text.

    a2) I have tried with Shape, which supports drawing text, but is less advanced with respect to geometry.

    a3) Could I use the strength in each of the two, and 'apply' a PathGeometry to a Shape?

    a4) I need to handle MouseOver after the drawing to highlight based on the mouse position. It can be done through computing 'behind the scenes' the object nearest mouse position (though possible, it's heavy!) but can the choice of rendering Control help me out?

    b1) I do not expect the end drawing to be subjectable to test?

    b2) How 'deep' should I reference controls belonging in the GUI? Gut feeling says no deeper than ViewModel (not business level), but the higher I keep it, the more code remains in places where they can't be unit tested.

Here are answers specific to WPF:

You can draw on a Canvas , wich lets you set element's position (Canvas.SetLeft, Canvas.SetTop, ...)

And you can perfectly use PathGeometry, Shape, etc... you should also have a loop at GeometryGroup which allows to group all geometry as one.

For the text, if you want text as a Geometry, you can use FormattedText with the BuildGeometry method..

About unit testing.

WPF databinding is very good with binding data, such as string to text box. It is less good with user commands. It is even worse with telling UI to do things, such as "draw line" - you may be able to come up with some funky ItemPresenter bound to collection of shape view models, but I imagine it would be hard and will introduce too many unnecessary artifacts. Bottom line: MVVM is probably not for this project.

Instead, you may use the "passive view" approach . You define a control-agnostic "virtual machine" interface for your view. Something like

interface IView
{
   void AddLine(int x1, int y1, int x2, int y2);
   void DrawText(...);
}

Your view should have a straightforward implementation of this interface with minimum logic: each method is maximum 2-3 lines, no conditions or loops. This is a "dumb" passive view which is not testable.

The rest of the system (namely, Presenter) talks to the IView interface and knows nothing about WPF or controls. Well, it may use some simple WPF types such as Color or Rectangle for convenience.

You can use mock library (eg Rhino Mocks) to write tests that make sure your Presenter makes the right calls to your passive view. You create a "mock" view and pass it to the presenter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM