Save Rendered Geometry of Shapes and use them in a custom shape - c#

We have an application and we need a custom shape per each signal(changeable value in time) to add it in canvas for having a reference. in future by changing the signal value shape must changing to. for example if value=1 the shape must be a rectangle and if value=2 shape must be an ellipse.
I want to save Geometry of these shapes in a list and use them when I want.
I have an Idea for this case but it dosent work.
public class DigitalShape : Shape
{
public Geometry SelectedGeometry
{
get { return (Geometry)GetValue(SelectedGeometryProperty); }
set { SetValue(SelectedGeometryProperty, value); }
}
public static readonly DependencyProperty SelectedGeometryProperty = DependencyProperty.Register("SelectedGeometry",
typeof(Geometry), typeof(DigitalShape), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
protected override Geometry DefiningGeometry
{
get
{
return SelectedGeometry;
}
}
}
Get geometries from shapes with RenderedGeometry like this:
Rectangle rect = new Rectangle();
rect.Width = 20;
rect.Height = 20;
rect.StrokeThickness = 1;
rect.Fill = Brushes.Yellow;
rect.Stroke = Brushes.Yellow;
Canvas.SetLeft(rect, 100);
Canvas.SetTop(rect, 100);
DigitalShape _symbolShape = new DigitalShape();
_symbolShape.SelectedGeometry = rect.RenderedGeometry;
please help me guys.
Update 1:
testing data property of path with this code in new project, but I didn't see the rectangle:
private void button1_Click(object sender, RoutedEventArgs e)
{
Rectangle rect = new Rectangle();
rect.Width = 20;
rect.Height = 20;
rect.StrokeThickness = 1;
rect.Fill = Brushes.Yellow;
rect.Stroke = Brushes.Yellow;
Canvas.SetLeft(rect, 100);
Canvas.SetTop(rect, 100);
Path path = new Path();
path.Data = rect.RenderedGeometry;
myCanvas.Children.Add(path);
}
Update 2:
using path from another way. when myElp is hard coded and created in xaml, rendergeometry is worked and get a right geometry with values but when I create myElp in Code behined rendergeometry give me an empty geometry.
Xaml Code:
<Grid>
<Canvas x:Name="myCanvas" Width="200" Height="200" Background="Aqua"/>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="62,234,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<Ellipse x:Name="myElp" Fill="#FFF4F4F5" Height="25" Margin="23,0,30,20" Stroke="Black"/>
</Grid>
Code Behined:
PathGeometry pathGeo = PathGeometry.CreateFromGeometry(myElp.RenderedGeometry);
Path path = new Path();
path.Data = pathGeo;
path.Stroke = Brushes.Yellow;
path.StrokeThickness = 1;
path.Fill = Brushes.Yellow;
Canvas.SetLeft(path, 10);
Canvas.SetTop(path, 10);
myCanvas.Children.Add(path);
I see 2 Ellipse when Run this code. 1 its own ellipse of xaml and 1 my path.
How can i use render geometry for shape who created in code behined?!

Related

WPF C# coded lines doesn't recognize coordinates origin

I'm exploring graphics capabilities of WPF+C#. Drawing a line with XAML makes what expected. ok.
To draw a simple line with C# code makes something "strange". The coordinates appear not where
they should be. Why? The following code should implement a diagonal from (0, 0) to (width, height) of
the container panel of the line.
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Line line1 = new Line
{
Stroke = Brushes.Black
};
Thickness thickness = new Thickness(10, -10, 36, 250);
line1.Margin = thickness;
line1.Visibility = Visibility.Visible;
line1.StrokeThickness = 4;
line1.X1 = 0;
line1.Y1 = 0;
line1.X2 = MainGrid.ActualWidth;
line1.Y2 = MainGrid.ActualHeight;
line1.HorizontalAlignment = HorizontalAlignment.Left;
MainGrid.Children.Add(line1);
}
It doesn't matter what panel you use: canvas, dockpanel, grid, stackpanel, I observed the same
strange and annoying behavior.
Not showing the diagonal. Not beginning at origin-vertex (0,0): (left,top)
Your problem is Thickness(10, -10, 36, 250). This arbitrary margin is cutting off the rest of the line. Here is a simplified version of your code that correctly draws a line from the top-left corner, to the bottom-right:
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Line line1 = new Line
{
Stroke = Brushes.Black,
StrokeThickness = 4,
X1 = 0,
Y1 = 0,
X2 = MainGrid.ActualWidth,
Y2 = MainGrid.ActualHeight
};
MainGrid.Children.Add(line1);
}
Note that Visibility = Visibility.Visible is left because Line (like most other elements) are visible by default.
You can do this much easier with a simple path statement - use Stretch="Fill" so there's no need to worry about dimensions
<Path Stroke="Black" StrokeThickness="4" Data="M 0,0 L 1,1" Stretch="Fill" />

annotated drawing must remain same position where it was done in WPF

i used WPF application and i have drawn a line on a dicom image.but my problem is when i resize main window, line positions are changed. it wont persist on the place where i drawn. i have tried with pointtoscreen method and translatepoint method. but didnt work. what is the correct way to do this.
i used two wpf image controls. one is to display the dicom image and other is on top of it to draw annotation.following is my wpf xaml code.
<Border x:Name="Border" ClipToBounds="True">
<Grid>
<Image x:Name="ImageTileViewer"
Margin="-234"
Source="{Binding CurrentImage}"
Stretch="None"
StretchDirection="DownOnly" RenderTransformOrigin="0.5,0.5"/>
<Grid Name="AnnotationImageGrid">
<Image Name="AnnotationImage" Stretch="None" RenderTransformOrigin="0.5,0.5"/>
</Grid>
</Grid>
<Grid>
<Canvas Name="canDrawing" Height="450" Width="800"
MouseMove="canDrawing_MouseMove_NotDown"
MouseDown="canDrawing_MouseDown">
<Image Name="imgTrash"
StretchDirection="DownOnly" RenderTransformOrigin="0.5,0.5"
Source="C:\Users\Chaithika\Downloads\after_resize.PNG" />
</Canvas>
</Grid>
public Window1()
{
InitializeComponent();
TransformGroup group = new TransformGroup();
ScaleTransform xform = new ScaleTransform();
group.Children.Add(xform);
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
imgTrash.RenderTransform = group;
canDrawing.RenderTransform = group;
}
private void Window1_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
var width = Convert.ToInt32(e.NewSize.Width);
var height = Convert.ToInt32(e.NewSize.Height);
double factor = Math.Min((width / imgTrash.ActualWidth), (height / imgTrash.ActualHeight));
if (width >= imgTrash.ActualWidth && height >= imgTrash.ActualHeight)
{
factor = 1;
}
TransformGroup transformGroup = (TransformGroup)imgTrash.RenderTransform;
ScaleTransform st = (ScaleTransform)transformGroup.Children[0];
st.ScaleX = factor;
st.ScaleY = factor;
TransformGroup transformGroup2 = (TransformGroup)canDrawing.RenderTransform;
ScaleTransform st2 = (ScaleTransform)transformGroup2.Children[0];
st2.ScaleX = factor;
st2.ScaleY = factor;
}

Rotate and Transform is not working when apply one by one in WPF

I am rotating the a panel (Grid) and Flip (Transform) the panel. When i do this separate, both are working fine. Rotate and then Flip (OR) Flip and Rotate is not working fine.
I am rotating the panel to 90 degree every time. When i rotate to 90 degree, the panel height and width is changed. In that case, if i Flip the panel, issue occur. For 180 degree, no issue.
Issue Steps
Step-1: Rotate image to 90 degree by clicking the rotate button in the sample. You will get the below output.
Step-2: Now Flip the image by Transform button and the image moved to left side. Expected output is, It should be center and Flip.
You can see the difference of Transformation of image, by directly clicking Transform button, without click on Rotate.
This is my code.
[XAML]:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid x:Name="grid1" Grid.Row="0">
<Image x:Name="image1" Source="Images/Buldingimage.jpeg"/>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Click="Button_Click_1" Grid.Column="0">Rotate</Button>
<Button Click="Button_Click_2" Grid.Column="1">Transform</Button>
</Grid>
</Grid>
[C#]:
double rotationAngle = 0;
private void Button_Click_1(object sender, RoutedEventArgs e)
{
//Rotate
this.rotationAngle += 90;
this.grid1.RenderTransformOrigin = new Point(0.5, 0.5);
this.grid1.LayoutTransform = new RotateTransform() { Angle = this.rotationAngle };
}
bool mIsHorizontalImageflipped = false;
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//Transform
int[] value ;
float[] origin = new float[] { 0.5f, 0.5f };
string path = "(UIElement.RenderTransform).(ScaleTransform.ScaleX)";
if (!this.mIsHorizontalImageflipped)
{
value = new int[] { 1, -1 };
this.mIsHorizontalImageflipped = true;
}
else
{
this.mIsHorizontalImageflipped = false;
value = new int[] { -1, 1 };
}
this.Animate(value, origin, path);
}
internal void Animate(int[] value, float[] origin, string path)
{
this.grid1.RenderTransform = new ScaleTransform();
Storyboard sb = new Storyboard();
this.grid1.RenderTransformOrigin = new Point(origin[0], origin[1]);
DoubleAnimationUsingKeyFrames keyFrames = new DoubleAnimationUsingKeyFrames();
SplineDoubleKeyFrame keyFrame = new SplineDoubleKeyFrame();
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
keyFrame.Value = value[0];
keyFrames.KeyFrames.Add(keyFrame);
keyFrame = new SplineDoubleKeyFrame();
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
KeySpline keySpline = new KeySpline();
keySpline.ControlPoint1 = new Point(0.64, 0.84);
keySpline.ControlPoint2 = new Point(0, 1);
keyFrame.KeySpline = keySpline;
keyFrames.KeyFrames.Add(keyFrame);
keyFrame.Value = value[1];
Storyboard.SetTargetProperty(keyFrames, new PropertyPath(path));
Storyboard.SetTarget(keyFrames, this.grid1);
sb.Children.Add(keyFrames);
sb.Begin();
}
Click here to download the sample.
Please provide suggestion or what i did wrong on this.
Regards,
Bharathi.
If you set the RenderTransform property to a ScaleTransform, you are effectively removing the RotateTransform and vice versa.
To be able to apply both transforms simultaneously, you could use a TransformGroup:
<Grid x:Name="grid1" Grid.Row="0">
<Image x:Name="image1" Source="Images/Buldingimage.jpeg"/>
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rt" />
<ScaleTransform x:Name="st" />
</TransformGroup>
</Grid.RenderTransform>
</Grid>
You would then simply change the Angle of the RotateTransform and animate the ScaleTransform as before:
double rotationAngle = 0;
private void Button_Click_1(object sender, RoutedEventArgs e)
{
//Rotate
this.rotationAngle += 90;
this.grid1.RenderTransformOrigin = new Point(0.5, 0.5);
rt.Angle = this.rotationAngle;
}
bool mIsHorizontalImageflipped = false;
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//Transform
int[] value;
float[] origin = new float[] { 0.5f, 0.5f };
string path = "RenderTransform.Children[1].ScaleX";
if (!this.mIsHorizontalImageflipped)
{
value = new int[] { 1, -1 };
this.mIsHorizontalImageflipped = true;
}
else
{
this.mIsHorizontalImageflipped = false;
value = new int[] { -1, 1 };
}
this.Animate(value, origin, path);
}
internal void Animate(int[] value, float[] origin, string path)
{
Storyboard sb = new Storyboard();
this.grid1.RenderTransformOrigin = new Point(origin[0], origin[1]);
DoubleAnimationUsingKeyFrames keyFrames = new DoubleAnimationUsingKeyFrames();
SplineDoubleKeyFrame keyFrame = new SplineDoubleKeyFrame();
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
keyFrame.Value = value[0];
keyFrames.KeyFrames.Add(keyFrame);
keyFrame = new SplineDoubleKeyFrame();
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
KeySpline keySpline = new KeySpline();
keySpline.ControlPoint1 = new Point(0.64, 0.84);
keySpline.ControlPoint2 = new Point(0, 1);
keyFrame.KeySpline = keySpline;
keyFrames.KeyFrames.Add(keyFrame);
keyFrame.Value = value[1];
Storyboard.SetTargetProperty(keyFrames, new PropertyPath(path));
Storyboard.SetTarget(keyFrames, this.grid1);
sb.Children.Add(keyFrames);
sb.Begin();
}

How to set Thickness value for Margin in doubleanimation (code not XAML) [duplicate]

Does anyone know of an easy way to animate a movement from an Image's current location to a new location (X,Y) using WPF animation with no XAML, 100% programmatically? And with no reference to "this" (with RegisterName etc).
I am trying to make an extension class for Image to do animation stuff on it. It is easy enough to change the width and height properties through animation, but after searching for location animation of an object it suddenly becomes more advanced.
As it is an extension class I will only have a reference to the actual Image object and the X and Y I want to move it to.
public static void MoveTo(this Image targetControl, double X, double Y, double Width, double Height){
//code here
...
}
Update:
Thanks. Almost working. It seems The GetTop and GetLeft returns 'NaN' not explicitly set. Found the workaround in this post: Canvas.GetTop() returning NaN
public static void MoveTo(this Image target, double newX, double newY) {
Vector offset = VisualTreeHelper.GetOffset(target);
var top = offset.Y;
var left = offset.X;
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
I had to swap two of the values (FROM) with 0. I assume that must be because in this context the upper left corner of the picture is the origin? But now it works.
Try this:
public static void MoveTo(this Image target, double newX, double newY)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.XProperty,anim1);
trans.BeginAnimation(TranslateTransform.YProperty,anim2);
}
Here it is... It changes the size and moves a MediaElement under the Canvas. Just input your parameters:
Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = mediaElement1.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = mediaElement1.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, mediaElement1.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, mediaElement1.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
<Viewbox Stretch="Uniform" StretchDirection="Both" SnapsToDevicePixels="True">
<Grid Width="640" Height="480" Name="MainLayout" SnapsToDevicePixels="True" Background="Black">
<Canvas Width="640" Height="480" Name="MainCanvas" SnapsToDevicePixels="True">
<MediaElement Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" LoadedBehavior="Manual" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" />
<Button Canvas.Left="294" Canvas.Top="196" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
</Canvas>
</Grid>
</Viewbox>
UPDATE:
Instead of MediaElement use this line:
<Rectangle Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" Fill="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}" />
And don't forget to put the C# code to:
private void button1_Click(object sender, RoutedEventArgs e) {}
You can use MediaElement as well but you have to define a VideoClip to see something ;)
Please find a solution that uses the Left and Top properties of Canvas for the extension method. See the following code:
public static void MoveTo(this Image target, Point newP)
{
Point oldP = new Point();
oldP.X = Canvas.GetLeft(target);
oldP.Y = Canvas.GetTop(target);
DoubleAnimation anim1 = new DoubleAnimation(oldP.X, newP.X, TimeSpan.FromSeconds(0.2));
DoubleAnimation anim2 = new DoubleAnimation(oldP.Y, newP.Y , TimeSpan.FromSeconds(0.2));
target.BeginAnimation(Canvas.LeftProperty , anim1);
target.BeginAnimation(Canvas.TopProperty, anim2);
}
This code is based on #DeanChalk's answer.
It moves an Image contained within a Canvas (RFID_Token) diagonally from the top-right to the bottom-left, positioned centrally over another Image within a Canvas (RFID_Reader).
<Canvas>
<Canvas x:Name="RFID_Reader_Canvas">
<Image x:Name="RFID_Reader" Source="RFID-Reader.png" Height="456" Width="682" Canvas.Left="37" Canvas.Top="524"/>
</Canvas>
<Canvas x:Name="RFID_Token_Canvas">
<Image x:Name="RFID_Token" Source="RFID-Token.png" Height="268" Width="343" Canvas.Left="874" Canvas.Top="70"/>
</Canvas>
</Canvas>
var StartX = Canvas.GetLeft(RFID_Token);
var StartY = Canvas.GetTop(RFID_Token);
var EndX = RFID_Reader.Width / 2 + Canvas.GetLeft(RFID_Reader) - StartX - (RFID_Token.Width / 2);
var EndY = RFID_Reader.Height / 2 + Canvas.GetTop(RFID_Reader) - StartY - (RFID_Token.Height / 2);
var AnimationX = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(1));
var AnimationY = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(1));
var Transform = new TranslateTransform();
RFID_Token_Canvas.RenderTransform = Transform;
Transform.BeginAnimation(TranslateTransform.XProperty, AnimationX);
Transform.BeginAnimation(TranslateTransform.YProperty, AnimationY);
I kept having NaN or 0 values for my nested elements, here's a modified version of Danny's answer :
public void MoveTo(Canvas canvas, FrameworkElement target, FrameworkElement destination)
{
Point oldPoint = target.TransformToAncestor(canvas).Transform(new Point(0, 0));
Point newPoint = destination.TransformToAncestor(canvas).Transform(new Point(0, 0));
var EndX = destination.Width / 2 + newPoint.X - oldPoint.X - (target.Width / 2);
var EndY = destination.Height / 2 + newPoint.Y - oldPoint.Y - (target.Height / 2);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(0.3));
DoubleAnimation anim2 = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(0.3));
trans.BeginAnimation(TranslateTransform.XProperty, anim1);
trans.BeginAnimation(TranslateTransform.YProperty, anim2);
}

Performance of Shapes versus DrawingVisual

MSDN writes:
DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout, input, focus, or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art.
I wrote a code drawing thousand lines via Line objects and thousand lines via DrawingVisual objects over an image. Comparing performance of both ways I haven't seen a difference. Scrolling a final picture isn't smooth enough in either case.
Why is the lag of scrolling identical in each case and where is the performance benefit of DrawingVisual?
The first way
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Canvas Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
Name="layoutView">
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<ImageDrawing x:Name="testImage"/>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Canvas>
</ScrollViewer>
and
ImageSource imageSource = new BitmapImage(uri);
testImage.Rect = new Rect(
0, 0, imageSource.Width, imageSource.Height);
testImage.ImageSource = imageSource;
layoutView.Width = imageSource.Width;
layoutView.Height = imageSource.Height;
Random r = new Random();
int max = Math.Min(
(int)imageSource.Height, (int)imageSource.Width);
for (int i = 0; i < 1000; i++)
{
Point p1 = new Point(r.Next(max), r.Next(max));
Point p2 = new Point(r.Next(max), r.Next(max));
Line line = new Line();
line.X1 = p1.X;
line.Y1 = p1.Y;
line.X2 = p2.X;
line.Y2 = p2.Y;
line.Stroke = Brushes.Red;
layoutView.Children.Add(line);
}
The second way
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<my:VisualView Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"
x:Name="layoutView">
</my:VisualView>
</ScrollViewer>
and
public class VisualView : Canvas
{
List<Visual> visuals = new List<Visual>();
protected override int VisualChildrenCount
{
get
{
return visuals.Count;
}
}
protected override Visual GetVisualChild(int index)
{
return visuals[index];
}
public void AddVisual(Visual visual)
{
visuals.Add(visual);
base.AddVisualChild(visual);
base.AddLogicalChild(visual);
}
public void RemoveVisual(Visual visual)
{
visuals.Remove(visual);
base.RemoveVisualChild(visual);
base.RemoveLogicalChild(visual);
}
}
and
ImageSource imageSource = new BitmapImage(uri);
Random r = new Random();
int max = Math.Min(
(int)imageSource.Height, (int)imageSource.Width);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
dc.DrawImage(imageSource, new Rect(
0, 0, imageSource.Width, imageSource.Height));
dc.Close();
layoutView.AddVisual(dv);
layoutView.Width = imageSource.Width;
layoutView.Height = imageSource.Height;
}
Pen pen = new Pen(Brushes.Red, 1);
for (int i = 0; i < 1000; i++)
{
dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
Point p1 = new Point(r.Next(max), r.Next(max));
Point p2 = new Point(r.Next(max), r.Next(max));
dc.DrawLine(pen, p1, p2);
dc.Close();
layoutView.AddVisual(dv);
}
}
You need to measure carefully to see the real difference. May be there are some WPF ETW events which can help.
If you're case, you have both images and vector graphics. If image is dominating perf here, then either way could be quite similar.
Try to remove images first to see if you see a difference.
With vectors, you should not create 1000 DrawingVisual, you can draw 1000 lines into a single Visual. You can even draw a single polyline.
With a single polyline, you can optimize further by removing points which are not affecting the shape of the line.

Categories