Line between 2 controls doesn't redraw - c#

I have b Buttons created dynamically by code and I want to draw a Line between the first node and the last in the same StackPanel. The problem is that whenever I call this function it doesn't make the line from the first to the b Button but instead it move the line to the right.
My code for the Line draw function:
public void CreateALine()
{
redLine = new Line();
redLine.X1 = nodul_nou[0].Margin.Left ;
redLine.Y1 = nodul_nou[b].Margin.Top - 40;
redLine.X2 = nodul_nou[b].Margin.Left ;
redLine.Y2 = nodul_nou[b].Margin.Top - 40;
SolidColorBrush redBrush = new SolidColorBrush();
redBrush.Color = Colors.Black;
redLine.StrokeThickness = 4;
redLine.Stroke = redBrush;
workplace.Children.Add(redLine);
}
Note: nodul_nou[b] is the Button I am speak about, It does not draw a line between the first Button, nodul_nou[0], and the b Button, nodul_nou[b].

Related

Is possible to draw shapes in C# wpf (grid), if the grid is split by rows and cells, and each row contains a stackpanel inside?

When I try to draw a shape, like a line, is working only in the first StackPanel
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.Y1 = 1;
myLine.X2 = 500;
myLine.Y2 = 50;
// myLine.HorizontalAlignment = HorizontalAlignment.Left;
// myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
gridAreaFight.Children.Add(myLine);
And here is the picture of the grid.
I try to create a Tower Defense game, and I want the towers to attack (with lines/shapes) on the grid, but it seems the draw method is working only in my first stack panel image (see the picture, in the left corner top). Is there something I'm not doing right? Or I should use something else instead drawing method for my towers?
You need to set row and column span for the line in order to draw it in whole available space. If you are drawing something on the grid without specific row and column, it defaults to column and row number 0.
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
Grid.SetRowSpan(myLine, n); // Here you are setting RowSpan. n-number of rows to span
Grid.SetColumnSpan(myLine, n); // Here you are setting ColumnSpan. n-number of columns to span
myLine.X1 = 1;
myLine.Y1 = 1;
myLine.X2 = 500;
myLine.Y2 = 50;
// myLine.HorizontalAlignment = HorizontalAlignment.Left;
// myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
area.Children.Add(myLine);

Draw a connector between shapes in wpf

I am creating some shapes from code behind dynamically and adding them to a Grid and further add the Grid to Canvas.
So when I double click on a shape I should be able to add some text which works fine. Now lets say I have two shapes on the Canvas and when I try to draw a line between these shapes for some reason the first shape gets pulled away to the bottom and the line starts from the middle of first shape.
I want the shape not to change the position and the line should start from the bottom of first shape. Please see the image for my problem.
Please help with your thoughts. Here is my code. Also I tried numerous posts eg: Getting the top left coordinates of a WPF UIElement.
But none of them seem to help.
private void CvsSurface_OnDrop(object sender, DragEventArgs e) //In this event I am creating a shape dynamically and adding to a grid which is then added to a canvas.
{
Shape result = null;
Object droppedData = e.Data; //This part is not important
/*Translate Drop Point in reference to Stack Panel*/
Point dropPoint = e.GetPosition(this.cvsSurface);
//Console.WriteLine(dropPoint);
//Label lbl = new Label();
//lbl.Content = draggedItem.Content;
UIElement element = draggedItem.Content as UIElement;
Shape s = element as Shape;
if (s is Ellipse)
{
Ellipse ellipse = new Ellipse()
{
Height = s.Height,
Width = s.Width,
Fill = s.Fill
};
result = ellipse;
}
else if (s is Rectangle)
{
Rectangle rectangle = new Rectangle()
{
Height = s.Height,
Width = s.Width,
Fill = s.Fill
};
result = rectangle;
}
Grid sp = new Grid();
sp.Children.Add(result);
sp.MouseLeftButtonDown += Sp_MouseLeftButtonDown;
sp.MouseLeftButtonUp += Sp_MouseLeftButtonUp;
//sp.PreviewMouseLeftButtonUp += Sp_PreviewMouseLeftButtonUp;
//sp.MouseLeftButtonUp += Sp_MouseLeftButtonUp;
cvsSurface.Children.Add(sp);
Canvas.SetLeft(sp, dropPoint.X);
Canvas.SetTop(sp, dropPoint.Y);
}
private void Sp_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) // The purpose of this event lets say when some one clicks on a shape and drags the mouse to the other shape and when mouse up I want to draw a line between the shapes.
{
bool mouserelease = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;
if (!mouserelease)
{
x2 = e.GetPosition(stackpanel).X;
y2 = e.GetPosition(stackpanel).Y;
Line l = new Line();
l.X1 = x1;
l.Y1 = y1;
l.X2 = x2;
l.Y2 = y2;
l.Margin = new Thickness(0, 19, 0, 0);
l.Stroke = new SolidColorBrush(Colors.Black);
l.StrokeThickness = 2;
stackpanel.Children.Add(l);
}
}
private void Sp_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) //This method lets say if user clicks twice then he wants to add some text or if he single clicks then I am assuming he is trying to a drag and draw a line
{
stackpanel = sender as Grid; //Sorry, the stackpanel is a global variable name of type Grid. Its actually Grid stackpanel;
if (e.ClickCount == 2)
{
dialog = new UserDialog()
{
DataContext = this,
Height = 180,
Width = 400,
MaxHeight = 180,
MaxWidth = 400
};
dialog.ShowDialog();
}
else
{
x1 = e.GetPosition(stackpanel).X + 18;
y1 = e.GetPosition(stackpanel).Y + 18;
//x1 = GetPosition(stackpanel, cvsSurface).X;
//y1 = GetPosition(stackpanel, cvsSurface).Y;
}
}

How to draw vertical line on mschart that fills graph but isn't infinite?

I am trying to draw a vertical line that is anchored to a point. I tried to use the height of my Y axis which is fixed to draw the line, but it wasn't centered correctly. So right now I have an infinite line, but that I want is the line to just fill the graph like so
VerticalLineAnnotation lineannot = new VerticalLineAnnotation();
lineannot.AnchorDataPoint = chart.Series[item].Points.Last();
lineannot.LineColor = Color.Red;
lineannot.Width = 3;
lineannot.Visible = true;
lineannot.IsInfinitive = true;
chart.Annotations.Add(lineannot);
IsInfinitive is complemented by ClipToChartArea; you can set the line to be clipped to a ChartArea like this:
lineannot.ClipToChartArea = chart.ChartAreas[item].Name;
assuming item is the right area name or index..
Note that ClipToChartArea takes the name of the chart area!
This is the simplest way to do it.
It is also possible to control an annotation's position and size directly:
// Note that directly after adding points this will return NaN:
double maxDataPoint = chart1.ChartAreas[0].AxisY.Maximum;
double minDataPoint = chart1.ChartAreas[0].AxisY.Minimum;
LineAnnotation annotation2 = new LineAnnotation();
annotation2.IsSizeAlwaysRelative = false;
annotation2.AxisX = chart1.ChartAreas[0].AxisX;
annotation2.AxisY = chart1.ChartAreas[0].AxisY;
annotation2.AnchorY = minDataPoint;
annotation2.Height = maxDataPoint - minDataPoint;;
annotation2.Width = 0;
annotation2.LineWidth = 2;
annotation2.StartCap = LineAnchorCapStyle.None;
annotation2.EndCap = LineAnchorCapStyle.None;
annotation2.AnchorX = 21; // <- your point
annotation2.LineColor = Color.Pink; // <- your color
chart1.Annotations.Add(annotation2);

Erase loaded image part by part in Windows Phone 7

I want to erase image loaded on canvas on mouse move and display the background image in wp7.
in C# MakeTransparent method is available.
But in windows phone no such method is available.
what to do ?
Canvas.Opacity = 0; //This will make the control transparent
Also you can use .Opacity function almost every visual user control (Image, Grid, Lists etc.)
Cleverly, you can use canvas_MouseMove event for an eraser effect.
Just subscribe to canvas mousemove event like in see the example below
//Canvas MouseMove Event
private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
{
currentPoint = e.GetPosition(this.canvas);
//Initialize line according to currentpoint position.
Line line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = oldPoint.X, Y2 = oldPoint.Y };
line.StrokeDashCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeThickness = 10;
line.Stroke = new SolidColorBrush(Colors.White) ;
////////////////////////////////
//Set color & thickness of line.
//Line add in canvas children to draw image & assign oldpoint.
this.canvas.Children.Add(line);
oldPoint = currentPoint;
}
Not too sure with it but still, I hope it helps.

How to call Binding function from a method?

I have a Slider Binded to the ScaleX of a Line, like the following code:
/* Graphics on Canvas */
Line lR = new Line();
lR.X1 = 0;
lR.Y1 = 0;
lR.X2 = 150;
lR.Y2 = 150;
lR.Stroke = new SolidColorBrush(Colors.Blue);
lR.StrokeThickness = 2;
/* declare ScaleTransformation */
ScaleTransform lRSt = new ScaleTransform();
TransformGroup lRTran = new TransformGroup();
lRTran.Children.Add(lRSt);
lR.RenderTransform = lRTran;
Binding sliderRBind1 = new Binding();
sliderRBind1.Source = sliderR;
sliderRBind1.Path = new PropertyPath("Value");
BindingOperations.SetBinding(lRSt, ScaleTransform.ScaleXProperty, sliderRBind1);
BindingOperations.SetBinding(lRSt, ScaleTransform.ScaleYProperty, sliderRBind1);
/* Slider - Slider should be placed outside the canvas to prevent being redrawn */
Slider sliderR = new Slider();
sliderR.Minimum = 1;
sliderR.Maximum = 3;
sliderR.Value = 1;
sliderR.TickPlacement = TickPlacement.BottomRight;
sliderR.TickFrequency = 0.2;
sliderR.IsSnapToTickEnabled = true;
Code works fine. But if I move the ScaleTransform to a method, the Binding is lost.
/* Graphics on Canvas */
Line lR = new Line();
lR.X1 = 0;
lR.Y1 = 0;
lR.X2 = 150;
lR.Y2 = 150;
lR.Stroke = new SolidColorBrush(Colors.Blue);
lR.StrokeThickness = 2;
/* declare ScaleTransformation */
ScaleTransform lRSt = new ScaleTransform();
TransformGroup lRTran = new TransformGroup();
lRTran.Children.Add(lRSt);
lR.RenderTransform = lRTran;
LineSliderR(lR);
/* Slider - Slider should be placed outside the canvas to prevent being redrawn */
Slider sliderR = new Slider();
sliderR.Minimum = 1;
sliderR.Maximum = 3;
sliderR.Value = 1;
sliderR.TickPlacement = TickPlacement.BottomRight;
sliderR.TickFrequency = 0.2;
sliderR.IsSnapToTickEnabled = true;
public void LineSliderR(Line lRSt)
{
Binding sliderRBind1 = new Binding();
sliderRBind1.Source = sliderR;
sliderRBind1.Path = new PropertyPath("Value");
BindingOperations.SetBinding(lRSt, ScaleTransform.ScaleXProperty, sliderRBind1);
BindingOperations.SetBinding(lRSt, ScaleTransform.ScaleYProperty, sliderRBind1);
}
Why did the Binding fail if it's called to a separate method?
The two codes are (to me) identical. Both contain four same, identical, "things":
a Line, a ScaleTransform, a Binding, and a Slider.
The first code has all 4 "things" in a function. The second code has the Binding call from a separate function. Both compiles without error: However, the Binding (between Line and Slider) works OK on the first code, but not the second. I am trying get the second code to work because I have many Line's and I don't want to repeat myself.
In your second code block, inside the method LineSliderR, lRSt is an object of type Line, while in your first block it is of type ScaleTransform.
If you want your second block to behave like the first, your method LineSliderR, should accept a ScaleTransform' as parameter:
public void LineSliderR(ScaleTransform lRSt)

Categories

Resources