Answered by:
Drawing elements from one canvas to another canvas

Question
-
Hi There,
I have a canvas (CanvasMain) with some usercontrols and inside the usercontrol I have image on it.
I want to draw the images of the position exactly on the CanvasMain to another of same size.
Can anybody help me out here???
Thanks
Diptimaya Patra
Monday, April 19, 2010 2:10 PM
Answers
-
Silverlight doesn't allow you to make direct copies of the object so you will need to make a new instance of the object and manually copy over the values.
You can get the Canvas.Left and Canvas.Top properties using the GetValue method on the object.
Button button; double left = (double)button.GetValue(Canvas.LeftProperty); double top = (double)button.GetValue(Canvas.TopProperty);
Here is a quick example to copy Rectangles from 1 Canvas to another:
XAML:
<UserControl x:Class="SilverlightApplication5.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Canvas x:Name="canvas1" Grid.Column="0" Margin="0"> <Rectangle Canvas.Left="100" Canvas.Top="100" Width="50" Height="50" Fill="Blue" /> <Rectangle Canvas.Left="0" Canvas.Top="0" Width="100" Height="100" Fill="Red" /> </Canvas> <Canvas x:Name="canvas2" Grid.Column="1" Margin="0"> </Canvas> <Button Grid.Row="1" Grid.ColumnSpan="2" Content="Copy" Click="Button_Click" /> </Grid> </UserControl>
C#:
private void Button_Click(object sender, RoutedEventArgs e) { IEnumerable<FrameworkElement> objects = GetChildsRecursive(canvas1); foreach (FrameworkElement obj in objects) { if (obj is Rectangle) { Rectangle copyObj = new Rectangle(); copyObj.Width = (double)obj.GetValue(Rectangle.WidthProperty); copyObj.Height = (double)obj.GetValue(Rectangle.HeightProperty); copyObj.Fill = (Brush)obj.GetValue(Rectangle.FillProperty); copyObj.SetValue(Canvas.LeftProperty, (double)obj.GetValue(Canvas.LeftProperty)); copyObj.SetValue(Canvas.TopProperty, (double)obj.GetValue(Canvas.TopProperty)); canvas2.Children.Add(copyObj); } } } IEnumerable<FrameworkElement> GetChildsRecursive(FrameworkElement root) { List<FrameworkElement> elts = new List<FrameworkElement>(); elts.Add(root); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) { FrameworkElement element = VisualTreeHelper.GetChild(root, i) as FrameworkElement; if (element != null) elts.AddRange(GetChildsRecursive(element)); } return elts; }
Monday, April 19, 2010 6:07 PM
All replies
-
You can traverse through the Canvas.Children properties in the first Canvas and copy the elements (with their Canvas.Left/Canvas.Top) properties to the next Canvas. You may need to create a new instance of the element and copy the properties because you may get an error that the element already exists in the old Canvas.
Monday, April 19, 2010 2:21 PM -
I am using the following method which gives me the list of UI elements present in the target control (In my case CanvasMain).
IEnumerable<DependencyObject> GetChildsRecursive(DependencyObject root) { List<DependencyObject> elts = new List<DependencyObject>(); elts.Add(root); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) elts.AddRange(GetChildsRecursive(VisualTreeHelper.GetChild(root, i))); return elts; }
Now how do I take the Canvas.Left and Canvas.Top properties. guide me. :)
Monday, April 19, 2010 2:41 PM -
Silverlight doesn't allow you to make direct copies of the object so you will need to make a new instance of the object and manually copy over the values.
You can get the Canvas.Left and Canvas.Top properties using the GetValue method on the object.
Button button; double left = (double)button.GetValue(Canvas.LeftProperty); double top = (double)button.GetValue(Canvas.TopProperty);
Here is a quick example to copy Rectangles from 1 Canvas to another:
XAML:
<UserControl x:Class="SilverlightApplication5.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Canvas x:Name="canvas1" Grid.Column="0" Margin="0"> <Rectangle Canvas.Left="100" Canvas.Top="100" Width="50" Height="50" Fill="Blue" /> <Rectangle Canvas.Left="0" Canvas.Top="0" Width="100" Height="100" Fill="Red" /> </Canvas> <Canvas x:Name="canvas2" Grid.Column="1" Margin="0"> </Canvas> <Button Grid.Row="1" Grid.ColumnSpan="2" Content="Copy" Click="Button_Click" /> </Grid> </UserControl>
C#:
private void Button_Click(object sender, RoutedEventArgs e) { IEnumerable<FrameworkElement> objects = GetChildsRecursive(canvas1); foreach (FrameworkElement obj in objects) { if (obj is Rectangle) { Rectangle copyObj = new Rectangle(); copyObj.Width = (double)obj.GetValue(Rectangle.WidthProperty); copyObj.Height = (double)obj.GetValue(Rectangle.HeightProperty); copyObj.Fill = (Brush)obj.GetValue(Rectangle.FillProperty); copyObj.SetValue(Canvas.LeftProperty, (double)obj.GetValue(Canvas.LeftProperty)); copyObj.SetValue(Canvas.TopProperty, (double)obj.GetValue(Canvas.TopProperty)); canvas2.Children.Add(copyObj); } } } IEnumerable<FrameworkElement> GetChildsRecursive(FrameworkElement root) { List<FrameworkElement> elts = new List<FrameworkElement>(); elts.Add(root); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) { FrameworkElement element = VisualTreeHelper.GetChild(root, i) as FrameworkElement; if (element != null) elts.AddRange(GetChildsRecursive(element)); } return elts; }
Monday, April 19, 2010 6:07 PM -
Thank you verymuch, it was a great help. I totally forgot about the GetValue method.
Monday, April 19, 2010 9:06 PM