Even though Microsoft provided lots of controls as well as 3rd parties, we still need to draw dynamic graphics, sometimes. I need to draw vector image based on input file which is just a series of x-y coordinates. Normalization and rescaling are not a problem but I didn't know how to draw it like GDI/GDI+ time.
In GDI+ we can draw things like
Graphics g = Graphics.FromImage(mf);
g.DrawLine(Pens.Blue, new Point(10, 10), new Point(100, 100));
But, WPF canvas is a collection of children objects. It's not a bitmap anymore.
So, we need to change our idea about drawings in here.
First off, a line object needs to be created.
using System.Windows.Shape;
using System.Windows.Media;
...
Line line = new Line();
line.Stroke = Brushes.LightSteelBlue;
line.StrokeThickness = 2;
line.X1 = 10;
line.Y1 = 10;
line.X2 = 100;
line.Y2 = 100;
Now, we can attach this to a container control. Let's add it onto a canvas. Alignments should be considered depends on the type of the container control.
line.HorizontalAlignment = HorizontalAlignment.Left;
line.VerticalAlignment = VerticalAlignment.Center;
freeCanvas.Children.Add(line);
Same way, a polygon can be added
Polygon p = new Polygon();
p.Stroke = Brushes.Black;
p.Fill = Brushes.LightBlue;
p.StrokeThickness = 1;
p.HorizontalAlignment = HorizontalAlignment.Left;
p.VerticalAlignment = VerticalAlignment.Center;
p.Points = new PointCollection() { new Point(10, 10), new Point(100, 100), new Point(200, 200) };
freeCanvas.Children.Add(p);
Pretty easy, huh! Interesting thing is that you can change any property of a Shape object after attaching it to the parent control and we can see the change without forcing to invalidate screen.
We can even hook up event handler to a Shape object to make dynamic behavior which reacts by a user input.
p.PreviewMouseDown += new MouseButtonEventHandler(Polygon_MouseDown);
p.MouseUp += new MouseButtonEventHandler(Polygon_MouseUp);
...
protected void Polygon_MouseDown(object sender, MouseButtonEventArgs e)
{
(sender as Shape).Fill = Brushes.Red;
}
protected void Polygon_MouseUp(object sender, MouseButtonEventArgs e)
{
(sender as Shape).Fill = Brushes.LightBlue;
}
...
Interesting! Since everything is a real object, we don't need to worry about redraw whenever UI's updated.
System.Windows.Shapes namespace has Ellipse, Line, Path, Polygon, Polyline, Rectangle as well as Shape as based class.
Love it. Thanks for the great info.
Answer Blip Trivia
Hi Mr. Chester Kim.
Thanks for your example.
I'm working trying something in the same ballpark, and get error:
"Specified Visual is already a child of another Visual or the root of a CompositionTarget."
Art
Hi Art, sorry for late response. I was lazy on maintaining this wiki, these days.
I'm not familiar to F# or Silverlight since my major project is only windows application.
Do you try to add certain control(shape) created by expression blend which already belongs to any of your screen?
I need to see your code to understand the situation.
Hi Chester Kim.
Hope all's well.
I've made some, epsilon, progress.
I've been working through Jon Harrop's Quick Hull article.
I like his GUI's use of option —-
let drag : int option ref = ref None;;
let size = 5.0;;
let mkEllipse i _ =
let ellipse = Shapes.Ellipse(Fill=Media.Brushes.Red, Width=size, Height=size)
ellipse.MouseRightButtonDown.Add(fun e -> drag := Some i)
ellipse.MouseUp.Add(fun e -> drag := None)
// ellipse.MouseDown.Add(fun e -> drag := Some i)
// ellipse.MouseUp.Add(fun e -> drag := None)
ellipse;;
Very interesting subject , appreciate it for posting . All human beings should try to learn before they die what they are running from, and to, and why. by James Thurber. dkdekedabbeeefee
My brother recommended I may like this website. He used to be totally right. This post truly made my day. You can not consider simply how so much time I had spent for this info! Thanks! keaakaaegbeefbbe
Very nice site!
Very nice site!
Post preview:
Close preview