I'm coding in Microsoft Visual Studio 2010 Express for Windows Phone. I need to add a point onto a Canvas, but I can't...
for (float x = x1; x < x2; x += dx)
{
Point poin = new Point();
poin.X = x;
poin.Y = Math.Sin(x);
canvas1.Children.Add(poin);
}
Studio says:
Error 2 Argument 1: cannot convert from 'System.Windows.Point' to 'System.Windows.UIElement'
My question is: how do I add a point onto a Canvas?
From your code snippet I assume you're trying to draw a curve. To do this, you can look into GraphicsPath. Instead of drawing individual points, you can use the points as coordinates, which you connect through lines. Then, in your code, you can create a GraphicsPath using the AddLine method.
This could then be drawn onto a bitmap, for example.
EDIT
Sample (not tested):
GraphicsPath p = new GraphicsPath();
for (float x = x1; x < x2; x += dx)
{
Point point = new Point();
point.X = x;
point.Y = Math.Sin(x);
Point point2 = new Point();
point2.X = x+dx;
point2.Y = Math.Sin(x+dx);
p.AddLine(point, point2);
}
graphics.DrawPath(p);
Another way would be to use the WPF Path class, which would work about the same, but is a real UI element which you can add to the children of a Canvas.
EDIT
People have pointed out that the above code is Windows Forms code. Well, here's what you can do in WPF:
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;
PointCollection points = new PointCollection();
for (float x = x1; x < x2; x += dx)
{
Point p = new Point(x, Math.Sin(x));
points.Add(p);
}
myPolygon.Points = points;
canvas1.Children.Add(myPolygon);
If it is 'just a single point you want to add, you can add a tiny rectangle or ellipse to the canvas.
If you want to set a lot of points or a couple points many times, I suggest you create an array of pixel data (colors) and write those to a WriteableBitmap
The Point you used is not a UIElement but a struct, please use Line instead.
Line lne = new Line();
lne.X1 = 10;
lne.X2 = 11;
lne.Y1 = 10;
lne.Y2 = 10;
canvas1.Children.Add(lne);
You get the idea...
Edit
changed:
lne.X2 = 10 to lne.X2 = 11
As per the error, the children of the Canvas control must be derivatives of the System.Windows.UIElement class: System.Windows.Point is not. To achieve what you are doing, you would be best looking into using the geometry within WPF. See here for an article on how to do so.
Try adding a ellipse
Ellipse myEllipse = new Ellipse();
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
myEllipse.Fill = mySolidColorBrush;
myEllipse.StrokeThickness = 2;
myEllipse.Stroke = Brushes.White;
myEllipse.Width = 200;
myEllipse.Height = 100;
Canvas.SetTop(myEllipse,50);
Canvas.SetLeft(myEllipse,80);
myCanvas.Children.Add(myEllipse);
Related
Currently, I have been doing a project on graphs on windows form. Now I have something to ask.
Is there by any chance a way to move the Stripeline label out of my chart and not have it in the chart to something like this What I expect it to be and also make my stripeline tinner because it is too thick
till date what i do
What I expect it to be
This is my stripline code in case you need it
StripLine stripLine1 = new StripLine();
stripLine1.StripWidth = 0.01;
stripLine1.BorderColor = System.Drawing.Color.Blue;
stripLine1.BorderWidth = 0;
stripLine1.BorderDashStyle = ChartDashStyle.Solid;
stripLine1.IntervalOffset = Convert.ToDouble(textBox7.Text);
stripLine1.BackColor = System.Drawing.Color.Blue;
stripLine1.Text = "x̅";
chart1.ChartAreas[0].AxisY.StripLines.Add(stripLine1);
No, StripLines are drawn inside their ChartArea only.
There are at least two options:
You can display their Text outside of it by coding a PaintXXX event, maybe like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
ChartArea ca = chart1.ChartAreas[0];
Axis ax = ca.AxisX;
Axis ay = ca.AxisY;
Graphics g = e.ChartGraphics.Graphics;
foreach (StripLine sl in ay.StripLines)
{
double v = (sl.Interval != double.NaN ? sl.Interval : 0) + sl.IntervalOffset;
TextRenderer.DrawText(g, sl.Text, sl.Font, new Point(
(int)ax.ValueToPixelPosition(ax.Maximum),
(int)ay.ValueToPixelPosition(v)),Color.Black);
}
}
Fine-tuning the position, maybe by honoring the TextAlignment properties is up to you..
Note that this will now display the text twice; a simple solution it to make the original label transparent:
YourStripLine.ForeColor = Color.Transparent;
Also note that drawn graphics will not get exported if you serialize the chart.
An alternative would be to set the secondary y-axis and add the labels as CustomLabels. On second thought, I think this is preferrable, at least if you don't need the secondary y-axis.
Here I do it for one stripline:
Axis ay2 = chart1.ChartAreas[0].AxisY2;
ay2.Enabled = AxisEnabled.True;
ay2.LineColor = Color.Transparent;
CustomLabel cl = new CustomLabel();
cl.Text = stripLine.Text;
double v = (stripLine.Interval != double.NaN ? stripLine.Interval : 0)
+ stripLine.IntervalOffset;
cl.FromPosition = v - 0.001;
cl.ToPosition = v + 0.001;
ay2.CustomLabels.Add(cl);
You here also will want to make the original text transparent.
Background: I am currently busy with showing position of a Vehicle on a Zoomable Canvas based on the Position (X,Y) and Orientation (for Rotation). I use Rectangle for visualizing the vehicle. Everything works well but I got a bit greedy and now I want to replace the Rectangle with Top View Picture of the Vehicle, so it looks that the vehicle itself is moving instead a Rectangle.
Code Below:
private void PaintLocationVehicle(VehicleClass vc)
{
IEnumerable<Rectangle> collection = vc.ZoomableCanvas.Children.OfType<Rectangle>().Where(x => x.Name == _vehicleobjectname);
List<Rectangle> listE = collection.ToList<Rectangle>();
for (int e = 0; e < listE.Count; e++)
vc.ZoomableCanvas.Children.Remove(listE[e]);
// Assign X and Y Position from Vehicle
double drawingX = vc.gCurrentX * GlobalVar.DrawingQ;
double drawingY = vc.gCurrentY * GlobalVar.DrawingQ;
// Scale Length and Width of Vehicle
double tractorWidthScaled = vc.tractorWidth * GlobalVar.DrawingQ;
double tractorLengthScaled = vc.tractorLength * GlobalVar.DrawingQ;
// Get Drawing Location
double _locationX = drawingX - (tractorLengthScaled / 2);
double _locationY = drawingY - ((tractorWidthScaled / 2));
RotateTransform rotation = new RotateTransform();
// Angle in 10th of a Degree
rotation.Angle = vc.gCurrentTheeta/10 ;
double i = 0;
//paint the node
Rectangle _rectangle = new Rectangle();
_rectangle.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString(vc.VehicleColor == "" ? "Black" : vc.VehicleColor));
_rectangle.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString(vc.VehicleColor == "" ? "Black" : vc.VehicleColor));
i += 0;
_rectangle.Width = tractorLengthScaled ;
_rectangle.Height = tractorWidthScaled;
rotation.CenterX = _rectangle.Width / 2;
rotation.CenterY = _rectangle.Height / 2;
_rectangle.RenderTransform = rotation;
Canvas.SetTop(_rectangle, _locationY + i);
Canvas.SetLeft(_rectangle, _locationX + i);
_rectangle.SetValue(ZoomableCanvas.ZIndexProperty, 2);
string _tooltipmsg = "Canvas: " + vc.ZoomableCanvas.Name;
// Assign ToolTip Values for User
_tooltipmsg += "\nX: " + vc.gCurrentX;
_tooltipmsg += "\nY: " + vc.gCurrentY;
_rectangle.ToolTip = _tooltipmsg;
_rectangle.Name = _vehicleobjectname;
//add to the canvas
vc.ZoomableCanvas.Children.Add(_rectangle);
}
Note: VehicleClass holds all the Values for a certain Vehicle. DrawingQ holds the transformation scale from Reality to Zoomable Canvas.
So the issues I forsee:
How to append the Size of a Jpeg file to get the size same as
Rectangle?
What kind of Shape object shall I use? Please
suggest.
If i undrestand you correctly. you wanted to show an image of the vechicle inside the rectangle. in order to do that you can use
ImageBrush and assign to the Rectangle Fill property
something like this
Rectangle rect = new Rectangle();
rect.Width = 100;
rect.Height = 100;
ImageBrush img = new ImageBrush();
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = new Uri("vehicle image path");
bmp.EndInit();
img.ImageSource = bmp;
rect.Fill = img;
I hope that helps
I have a uniform grid that has rectangles dynamically added to it. I want to remove a particular rectangle, but I am getting the following error when trying to pass it to the Remove method:
Cannot convert from 'System.Drawing.Rectangle' to 'System.Windows.UIElement'
My code is:
Rectangle swatch = (Rectangle)ug_Thumbnails.FindName("s_" + _instance);
ug_Thumbnails.Children.Remove(swatch);
I tried casting, and got an error saying that you couldn't do it.
EDIT: Per request, here's the code to create the rectangle:
System.Windows.Shapes.Rectangle swatch = new System.Windows.Shapes.Rectangle();
swatch.Width = 50;
swatch.Height = 50;
swatch.Margin = new Thickness(0, 5, 5, 0);
swatch.StrokeThickness = 1;
swatch.Stroke = System.Windows.Media.Brushes.Gray;
swatch.Name = "s_" + name.ToString();
double groupsize = 100 / colors.Count();
DrawingBrush blackBrush = new DrawingBrush();
DrawingGroup checkersDrawingGroup = new DrawingGroup();
List<SolidColorBrush> brushes = colors;
double location = 0;
for (int i = 0; i < colors.Count(); i++)
{
GeometryDrawing drawing = new GeometryDrawing(brushes[i], null,
new RectangleGeometry(new Rect(location, 0, groupsize, groupsize)));
checkersDrawingGroup.Children.Add(drawing);
location += groupsize;
}
blackBrush.Drawing = checkersDrawingGroup;
swatch.Fill = blackBrush;
swatch.MouseUp += new MouseButtonEventHandler(loadSwatchResources);
ug_Thumbnails.Children.Add(swatch);
You need to use the Rectangle in System.Windows.Shapes when trying to reference a rectangle in WPF. This is specifically for rectangles in WPF and as such is a bit different than the System.Drawing rectangle class. You should be able to cast to this version of rectangle since it derives from FrameworkElement. See http://msdn.microsoft.com/en-us/library/system.windows.shapes.rectangle(v=vs.110).aspx for more info.
I have encountered a very odd problem today using WPF. Here is the code I have used to draw 10000 LineGeometry objects.
// Draw 10000 lines
var g = new GeometryGroup();
var x = 0;
var y = 0;
var n = 1;
while (n < 10000)
{
x = x + 20;
if (x > 600)
{
x = 0;
y = y + 20;
}
var l = new LineGeometry
{
StartPoint = new Point(x, y),
EndPoint = new Point(x, y + 15)
};
g.Children.Add(l);
n++;
}
var drawing = new GeometryDrawing {Geometry = g};
var drawingGroup = new DrawingGroup();
drawingGroup.Children.Add(drawing);
var myPen = new Pen {Thickness = 1, Brush = Brushes.Yellow};
drawing.Pen = myPen;
var myImage = new Image {Stretch = Stretch.None, Margin = new Thickness(10)};
var myDrawingImage = new DrawingImage {Drawing = drawingGroup};
myImage.Source = myDrawingImage;
canvas.Children.Add(myImage);
Now as you can see the result is not crisp and I used the code below to achieve better results.
RenderOptions.SetEdgeMode(myImage, EdgeMode.Aliased);
The image gets crisp but has another side effects as you can see in the image below.
Some lines are now shown.
Some extra odd lines are shown.
I have included the full code so you can experiment this for yourself.
Note:
I'm using ZoomBorder class around the Canvas canvas.
Pan & Zoom Image
Have you tried using
RenderOptions.SetBitmapScalingMode(myImage, BitmapScalingMode.HighQuality);
instead?
You can also set it on your Canvas control as well..
<Canvas RenderOptions.BitmapScalingMode="HighQuality"> ...
This is not a real answer but I want add something to that odd behavior of WPF in hope somebody can come up with a real explanation.
I added a single line from (0,0)-(20000,20000). Creating 8000 line objects (n < 8000) produces the expected result like this:
Now, creating 9000 line objects will totally mess it up, but see for yourself:
Without setting EdgeMode.Aliased it looks fine, even with high counts of objects.
I have used this code to draw a set of ellipses in C# but I do not know how to erase them. Any help would be greatly appreciated. Here is the code I use to draw:
private void drawEllipseAnimation(double x, double y)
{
Ellipse e = new Ellipse();
e.Fill = Brushes.Yellow;
e.Stroke = Brushes.Black;
e.Height = 10;
e.Width = 10;
e.Opacity = 1;
MainCanvas.Children.Add(e);
Canvas.SetLeft(e, x);
Canvas.SetTop(e, y);
}
MainCanvas.Children.Clear()?