Add event handler (MouseDown) dynamically for PathFigure C# WPF - wpf

I created an object from points with this code, dynamically:
SolidColorBrush brushColor = (SolidColorBrush)new BrushConverter().ConvertFromString(_brushColor);
PathFigure figures = new PathFigure();
figures.StartPoint = points[0];
points.RemoveAt(0);
figures.Segments = new PathSegmentCollection(points.Select((p, i) => new LineSegment(p, i % 2 == 0)));
PathGeometry pg = new PathGeometry();
pg.Figures.Add(figures);
canvas.Children.Add(new Path { Stroke = brushColor, StrokeThickness = 3, Data = pg });
Now I want to add event handler for this object. Would not be a problem if object is a path or polyline type. I would just add event handler like this:
poly.MouseDown += new MouseButtonEventHandler(poly_MouseDown);
void poly_MouseDown(object sender, MouseButtonEventArgs e)
{
//code
}
Problem is that I have to use Figures and PathGeometry which does not accept MouseDown event handlers. Since they are from System.Windows.Media class and Path/Polyline is from System.Windows.Shapes I can't find a solution to assign right event handler (MouseDown) to my Figure object.
What is the solution or is there any nice workaround solution for this problem? Maybe cast or convert it somehow?

As I see it you're skipping a crucial step.
Declare the Path Object first, give it the event, and then insert it into your Canvas:
SolidColorBrush brushColor = (SolidColorBrush)new BrushConverter ().ConvertFromString (_brushColor);
PathFigure figures = new PathFigure ();
figures.StartPoint = points[0];
points.RemoveAt (0);
figures.Segments = new PathSegmentCollection (points.Select ((p, i) => new LineSegment (p, i % 2 == 0)));
PathGeometry pg = new PathGeometry ();
pg.Figures.Add (figures);
Path pgObject = new Path({ Stroke = brushColor, StrokeThickness = 3, Data = pg });
pgObject.MouseDown+=new MouseButtonEventHandler(poly_MouseDown);
canvas.Children.Add (pgObject);

Related

WPF - pass data from page A to page B

So I want to pass data when I clicked an Canvas. So I have this code;
Canvas event_canvas = new Canvas();
event_canvas.Background = new SolidColorBrush(Color.FromRgb(66, 70, 77));
event_canvas.Width = 250;
event_canvas.Height = 60;
event_canvas.Margin = new Thickness(40, 0, 0, 0);
event_canvas.HorizontalAlignment = HorizontalAlignment.Left;
event_canvas.VerticalAlignment = VerticalAlignment.Top;
event_canvas.Cursor = Cursors.Hand;
#endregion
#region Grid (event_grid)
Grid event_grid = new Grid();
event_grid.Width = 250;
event_grid.Height = 60;
#endregion
#region TextBlock (event_text)
TextBlock event_text = new TextBlock();
event_text.VerticalAlignment = VerticalAlignment.Center;
event_text.HorizontalAlignment = HorizontalAlignment.Center;
event_text.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
event_text.Text = e.name;
#endregion
event_grid.Children.Add(event_text); // Add the textblock to the grid
event_canvas.Children.Add(event_grid); // Add the grid to the canvas
grid_events.Children.Add(event_canvas); // Add the canvas to the main grid.
// Click event registration
event_canvas.MouseLeftButtonDown += Event_canvas_MouseLeftButtonDown;
And then in the trigger;
private void Event_canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Page pg = new EventDetailPage();
// Replaces all the content!!!!!
this.Content = pg;
//throw new NotImplementedException();
}
I tried to add this;
var param = ((TextBlock)sender).Text;
Page pg = new EventDetailPage(param);
But that code doesn't work, it throws an error that I can't get a value.
How can I fix this issue?
Cast the sender argument to Canvas and then access the Grid through the Canvas' Children collecton and the TextBlock through the Grid's Children collecton:
private void Event_canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Canvas canvas = (Canvas)sender;
Grid event_grid = canvas.Children[0] as Grid;
TextBlock event_text = event_grid.Children[0] as TextBlock;
string text = event_text.Text;
...
}

Get DoubleAnimation Reference Object from BeginAnimation

I want to add a simple double animation with code-behind to apply a fadein to n objects created at runtime:
foreach (var rect in howmanyrect) {
Rectangle bbox = new Rectangle {
Width = rect.Width,
Height = rect.Height,
Stroke = Brushes.BlueViolet,
Opacity = 0D
};
DoubleAnimation da = new DoubleAnimation {
From = 0D,
To = 1D,
Duration = TimeSpan.FromMilliseconds(500D),
RepeatBehavior = new RepeatBehavior(1),
AutoReverse = false
};
GridContainer.Children.Add(bbox);
Canvas.SetLeft(bbox, rect.Left);
Canvas.SetTop(bbox, rect.Top);
bbox.Tag = da; // <- Look HERE
bbox.BeginAnimation(OpacityProperty, da);
After this, when requested, delete the objects collection with fadeout:
foreach (var child in GridContainer.Children) {
Rectangle bbox = (Rectangle) child;
DoubleAnimation da = (DoubleAnimation) bbox.Tag; // <- Look HERE
da.From = 1D;
da.To = 0D;
var childCopy = child; // This copy grants the object reference access for removing inside a forech statement
da.Completed += (obj, arg) => viewerGrid.Children.Remove((UIElement) childCopy);
bbox.BeginAnimation(OpacityProperty, da);
}
This code works perfectly but it's a workaround. In my first revision I created a new Doubleanimation object in the delete method but when I started the animation every object excetutes the first and the second animation before being deleted.
So I decide to pass a reference to the DoubleAnimation instance with the Tag property and change the animation properties.
Is there another way to obtain a reference to the DoubleAnimation object attached with BeginAnimation or to avoid the first animation to be repeated?
Thanks
Lox

WPF Animating a Run element to flash

This is kind of a weird problem I am having right now. What I am trying to do is animate a Run element to essentially flash/blink. The parent is a Hyperlink which contains multiple Inlines of type Run and Image. Now I am trying to animate the Foreground color of the element but it does not seem to work.
Here is my code for a hyperlink.
CallbackHyperLink callbackLink = new CallbackHyperLink();
ToolTipService.SetShowDuration(callbackLink, 3600000);
ToolTipService.SetInitialShowDelay(callbackLink, 0);
callbackLink.Foreground = new SolidColorBrush(Colors.Magenta); // Default text color of the link
callbackLink.TextDecorations = null; // Disable the underline until mouse over
callbackLink.ToolTip = f.Tooltip; // Set the tooltip string
DoubleAnimation opacityAnim = new DoubleAnimation();
opacityAnim.From = 1.0;
opacityAnim.To = 0.0;
opacityAnim.FillBehavior = FillBehavior.Stop;
opacityAnim.Duration = TimeSpan.FromSeconds(BlinkDurationOff);
opacityAnim.AutoReverse = true;
_blinkAnimation.Children.Add(opacityAnim);
Storyboard.SetTarget(opacityAnim, callbackLink.Foreground);
Storyboard.SetTargetProperty(opacityAnim, new PropertyPath(SolidColorBrush.OpacityProperty));
_blinkAnimation.Stop();
_blinkAnimation.Begin();
So that gets put in a storyboard which get fired. However the foreground is not getting animated and I am not seeing any warnings that im trying to animate something I shouldn't. Anybody have any ideas?
Thanks
This works:
Storyboard.SetTarget(opacityAnim, callbackLink);
Storyboard.SetTargetProperty(opacityAnim, new PropertyPath(UIElement.OpacityProperty));
Edit full working example with a TextBlock stolen from here :
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
TextBlock callbackLink = new TextBlock();
callbackLink.HorizontalAlignment = HorizontalAlignment.Center;
callbackLink.VerticalAlignment = VerticalAlignment.Center;
callbackLink.Text = "Test";
this.Content = callbackLink;
NameScope.SetNameScope(this, new NameScope());
var b = new SolidColorBrush(Colors.Magenta);
callbackLink.Foreground = b;
this.RegisterName("MyAnimatedBrush", b);
DoubleAnimation opacityAnimation = new DoubleAnimation();
opacityAnimation.To = 0.0;
opacityAnimation.Duration = TimeSpan.FromSeconds(0.5);
opacityAnimation.AutoReverse = true;
opacityAnimation.RepeatBehavior = RepeatBehavior.Forever;
Storyboard.SetTargetName(opacityAnimation, "MyAnimatedBrush");
Storyboard.SetTargetProperty(
opacityAnimation, new PropertyPath(SolidColorBrush.OpacityProperty));
Storyboard mouseLeftButtonDownStoryboard = new Storyboard();
mouseLeftButtonDownStoryboard.Children.Add(opacityAnimation);
callbackLink.MouseEnter += delegate(object sender2, MouseEventArgs ee)
{
mouseLeftButtonDownStoryboard.Begin(this, true);
};
callbackLink.MouseLeave += delegate(object sender2, MouseEventArgs ee)
{
mouseLeftButtonDownStoryboard.Stop(this);
};
}
Also another way to link to the foreground opacity call without registering the name of the brush is the following.
Storyboard.SetTarget(opacityAnim, callbackLink);
Storyboard.SetTargetProperty(opacityAnim, new PropertyPath("Foreground.Opacity"));
This seems to finally work for me. Still tweaking my solution as I am doing a lot of Stop/Begin calls on the animation which I believe is not good way of doing things.

How can I slide a button/textbox or any control in WPF?

I want to simply animate a text-box such that it fades in and also moves to the left (or any x/y position). How can I achieve that?
Also will it matter if it's inside a Grid?
Here's a sketchy method i just wrote for fading in any kind of UIElement:
public static void FadeIn(UIElement element, int xOffset, TimeSpan duration)
{
Transform tempTrans = element.RenderTransform;
TranslateTransform trans = new TranslateTransform(xOffset, 0);
TransformGroup group = new TransformGroup();
if (tempTrans != null) group.Children.Add(tempTrans);
group.Children.Add(trans);
DoubleAnimation animTranslate = new DoubleAnimation(0, (Duration)duration);
animTranslate.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
DoubleAnimation animFadeIn = new DoubleAnimation(0, 1, (Duration)duration) { FillBehavior = FillBehavior.Stop };
animTranslate.Completed += delegate
{
element.RenderTransform = tempTrans;
};
element.RenderTransform = trans;
element.BeginAnimation(UIElement.OpacityProperty, animFadeIn);
trans.BeginAnimation(TranslateTransform.XProperty, animTranslate);
}
If some of the workings are not clear feel free to ask.

WPF: Get specify image from touch

I was added picture as a children to layer called "canvas". By the following code:
if (addChild)
{
Image i = new Image();
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(path, UriKind.Absolute);
src.EndInit();
i.Source = src;
i.Width = 200;
i.IsManipulationEnabled = true;
double rotAngle = Rand.GetRandomDouble(-3.14/4, 3.14/4);
i.RenderTransform = new MatrixTransform(Math.Cos(rotAngle), -Math.Sin(rotAngle),
Math.Sin(rotAngle), Math.Cos(rotAngle), Rand.GetRandomDouble(0, this.Width - i.Width), Rand.GetRandomDouble(0, this.Height - i.Width));
canvasImages.Add(i);
canvas.Children.Add(i);
Canvas.SetZIndex(i, canvas.Children.Count-1);
addedFiles.Add(path);
maxZ++;
}
Here is the problem. I'm trying to make an event called "canvas_TouchDown" which can detect the specify picture when I touched it so that it will get the center of that image object.
List<Image> canvasImages = new List<Image>();
private void canvas_TouchDown(object sender, TouchEventArgs e)
{
foreach (Image canvasImage in canvasImages)
{
if (canvasImage.AreAnyTouchesCaptured == true)
{
System.Diagnostics.Debug.WriteLine("I found image that you touch");
}
}
}
However, there is nothing happened. I also try to use PersistId property but it doesn't work. Have any suggestion?
Regard,
C.Porawat
If you are adding the image to the canvas, touching it and expecting the canvas to receive the touch you will be disappointed. You should either listen to "touch down" on the image or "preview touch down" on the canvas.

Resources