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

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 (e.g. 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.

Related

C# WPF: Complex Shape objects on a Canvas? MVVM

This is more of a "Is it possible (with a reasonable amount of time and work)" than a "how exactly is it possible" question. I'm getting into WPF at the moment and am interested in graphical applications in an MVVM approach. In the meaning of an ms-paint like application. Now I see that and how I can draw e.g. a ractangle on a canvas, store those rectangles in a list etc.
But I am wondering if I can do that more advanced. For example extend the rectangle so I can give it more infos (I can't extend the rectangle itself since it's a sealed class), have existing shapes on the canvas able to drag them around, make the shapes complex (e.g. I double click one to open a new Window that represents the "inside" of that shape) etc.
Is such an application possible with a reasonable amount of work and time in WPF or would I rather use some different library/framework for this?
Yes, It is possible, Actually, you are listing CAD specifications, In fact, I work on this type of technology, so I'll suggest you some resources to have a clue..
Take a look at this project(WPF, 2D)
And this one(WPF, 3D)
And this one(WPF, 2D)
The previous projects are WPF-based, also, you might host a WinForm control in your WPF app, take a look at this one(WinForms, 2D)
If you change the specification a bit and say: "I don't want to edit the drawings on the canvas", then you could go with this option: convert your shapes to PathFigureCollection and EllipseGeometry objects, then construct Paths from these objects and add the Paths to the Canvas, this is a pure WPF approach. Indeed, you can add traditinal controls like TextBlocks as children to your Canvas, I have done such one like this..
Hope it helps.

C# UWP Universal Windows App - Shape Resizing

I'm working on an application that has a graphic editor. Aside from some other graphic components the main feature are some shapes (rectangles, triangles, stars etc.). The thing I would like to do is to have the ability to resize them after a double click, so there should be a container shown with points that can be dragged to resize the shape. There are many great tutorials out in the internet but mainly for rectangles or for other shapes that are "packed" into rectangle viewboxes.
The issue is that I need to have my resize points exactly on the vertexes, so for example I can't have a triangle inside a rectangle viewbox, but I need exactly three points - one on every vertex. The same applies for the other shapes like stars and arrows which are much more complicated.
Here's what I mean:
So I think I have two ways. Either pass a dynamic list of points after a double click and display them as separate shapes or binding them with my shape inside my shape class, but I cannot figure out how to add multiple shapes to a viewbox so that they keep their abilities. Here is a simplified snippet of how my shape classes look like:
public class RectangleObject : ShapeObject
{
private Rectangle _rectangle;
private Viewbox _viewbox;
public RectangleObject(Color fillColor)
{
_rectangle = new Rectangle()
{
Fill = new SolidColorBrush(fillColor),
Stretch = Stretch.Fill
};
_viewbox.child = _rectangle;
}
public void SetDimensions(){}
//... and some other methods
}
A nice solution would be if the viewbox could contain my shape and the resize points but I will appreciate any advice. I know that a canvas would be a better solution but all other components are packed in viewboxes so it would be problematic because of inheritance and would need many changes. Thanks in advance!
Yes I know exactly what you mean. I used CorelDraw back in the day and then Adobe Illustrator and both had the concept of shape transformation mode (your image on the right) as well as vertex edit mode (your image on the left). UWP is similar to WPF and WPF has a concept of adorners which you can customise to do whatever you want including what I just described.
So when you enter one of these modes, rather than modify your existing shape to show selectors; instead you create adorners that are superimposed over the shape. That way one doesn't clobber the other and you may have custom behavior for each as you indicated.
See also
Adorners - MSDN, https://msdn.microsoft.com/en-us/library/ms743737(v=vs.110).aspx, retrieved 2017-1-12

Drawing dynamic polygons in WPF

I am not sure if this is the right place to ask for such concept information advice, so I apologise if it's unrelated or off-topic to ask in Stack Overflow.
I want to develop an application in WPF which has the ability to draw polygons with the functionality of a regular control, they may change shape by adding, removing or moving vertices, change brushes all by run-time, from data-binding or perhaps direct manipulating from C# code (still not sure about that).
What I am trying to achieve is an application which draws a map and the shapes on it are the entities with the dynamic borders over the map (for instance say political borders). The polygons also have to be clickable controls with collision test (not just a bounding box, but exactly by the shape of the entity on the map). I can expect the shapes to be very detailed because of borders which found by rivers and mountains or other natural objects which not just a straight line of two vertices, so it's performance should be an important factor here because one polygon may contain hundreds of vertices).
What I've concluded that it is possible to achieve via WPF such an application. But my uncertainty is on the most efficient way to implement the map drawing, perhaps I should implement D3D hosting like SharpDX but I don't want it, it would make things even more complicated and difficult.
I prefer everything in this map to be functional as a regular WPF control with it's data-binding and stylising abilities. I've developed with WPF some several small test projects for months to learn the basics and its main concept. But now comes the main interest of mine to develop with WPF. I need some advice please, because drawing complicated and dynamic shapes is still not really clear to me to just go on and start develop it.
I would use WPF, indeed I would say WPF is perfect for this, though there will be considerable amount to learn. WPF uses DirectX so is preformant enough I imagine (provided you have the hardware).
You will need to become familiar with:
UserControl
DependencyProperties
Polygon
Canvas
However if you are not already familiar with Dependency Properties, they can be a headache to learn, so rather than creating your own UserControl with them, you can get away with a Canvas in your Window and build things programmatically or at design time in XAML.
As for actually drawing shapes; if you know ahead of time what the shapes will look like you can draw them ahead of time using tool like Blend (or by yourself in XAML - you will need to become familiar with the Path Markup Syntax) then you can use transforms such as a ScaleTransform to transform them at run-time, or if you want to build them at run-time you can do so programmatically adding points to a Polygon
e.g. from (Polygon)
//Add the Polygon Element
myPolygon = new Polygon();
myPolygon.Stroke = System.Windows.Media.Brushes.Black;
myPolygon.Fill = System.Windows.Media.Brushes.LightSeaGreen;
myPolygon.StrokeThickness = 2;
myPolygon.HorizontalAlignment = HorizontalAlignment.Left;
myPolygon.VerticalAlignment = VerticalAlignment.Center;
System.Windows.Point Point1 = new System.Windows.Point(1, 50);
System.Windows.Point Point2 = new System.Windows.Point(10,80);
System.Windows.Point Point3 = new System.Windows.Point(50,50);
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(Point1);
myPointCollection.Add(Point2);
myPointCollection.Add(Point3);
myPolygon.Points = myPointCollection;
myGrid.Children.Add(myPolygon);

Partially shaded circle timer in WPF

Where can I get started drawing animated geometry in C#? I would like to draw a sort of countdown timer by drawing a partially shaded circle. At start the circle would be fully shaded, at 75% 3/4 of the circle would be shaded and at 0 completely unshaded. I really don't know where to begin with something like this.
If you still don't understand what I need, a lot of games use this sort of animation to represent a "cooldown" on an item or skill. Like a second hand going around a clock, revealing what is beneath it.
WPF is my target application but I imagine I will need to use some sort of GDI api.
You could start out with the drawing examples here, for how to make your pie-like graphic:
http://www.codeproject.com/KB/WPF/PieChartDataBinding.aspx
It looks like they use StreamGeometryContext, along with LineTo and ArcTo.
You could then work on applying an animation to the properties on that graphic, so the "slice" gets bigger over time, by changing the arc length:
http://msdn.microsoft.com/en-us/library/ms752312.aspx#applyanimationstoproperty
You could then wrap this all up nicely in a UserControl, with custom dependency properties, so you can reuse this throughout your app.
Edit: I was thinking you meant the shaded pie like in World of Warcraft. What you want is actually simpler. See can poyrazoğlu's answer for the graphical approach to take (although you really only need the top black circle, if you're going with an opacity approach).
Yes, it's really easy with WPF.
Just create another circle on top of the circle, make that one black, and let a timer update the opacity of the top circle from 1 to 0 by time (or whatever you want).
This is the "easy" way. A more "convenient", or "WPF-style" approach would include Bindings and possibly value conversions, you'll be binding the opacity of the circle to a custom value with a value converter (or decrementing that value, anyway there are lots of ways).
Choose whatever you want. They'll both work.

C#: Drawing only a portion of a path

I have a series of points in a GraphicsPath; for our purpose lets assume its the outline of an uppercase B. I want to be able to be able to draw only the bottom portion that would resemble an uppercase L.
I'd like to be able to select a window of points from the GraphicsPath. Is there a handy way to do this without doing point interpolation; ie have to write code to calculate slope math and possibly derivatives?
I don't believe that there's a way to actually tell the Graphics class to "stop" halfway through a path, or somehow create a new path that intersects with a bounding box (without implementing the method yourself), but if you're just doing this so you can draw a certain part of the path, then you should be able to achieve what you want by setting the clipping region.
See the Graphics.ClipBounds property, which takes a RectangleF, or Graphics.Clip, which is a Region (the former is generally easier to use, unless you already have a Region instance).
If you need to use the partial path for something else then I'm not aware of any built-in way to do it.

Categories

Resources