locked
Drawing elements from one canvas to another canvas RRS feed

  • 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. Geeked

    Monday, April 19, 2010 9:06 PM