tags:

views:

52

answers:

4

Hi, I've been using Children.Add with different default silverlight controls adding them to canvases. What I don't get is why something like this is possible:

Rectangle rec = new Rectangle(){...};
canvas.Children.Add(rec);

but not something like this (doesn't even compile):

myRectangle rec = new myRectangle();    
canvas.Children.Add(rec);

myRectangle being just a wrapper to a rectangle

I'm sure I'm missing something fundamental.. Thanks for any help.


myRectangle class:

public class myRectangle
{
        private SolidColorBrush fillColor;
        private Rectangle recNewColor;

        internal myRectangle()
        {
            fillColor = new SolidColorBrush(Colors.White);
            LinearGradientBrush strokeBrush = new LinearGradientBrush()
            {
                StartPoint = new Point(0.5, 0),
                EndPoint = new Point(0.5, 1),
                GradientStops = 
                { 
                    new GradientStop() { Color = Colors.Red, Offset = 1.0 },
                    new GradientStop() { Color = Colors.Orange, Offset = 0.0 },
                }
            };
            recNewColor = new Rectangle()
            {
                Stroke = strokeBrush,
                Height = 20,
                Width = 20,
                Fill = fillColor,
                HorizontalAlignment = HorizontalAlignment.Left,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = new Thickness() { Bottom = 5, Left = 5 },
            };
        }
...
}
+2  A: 
myRectangle rec = new myRectangle();     
canvas.Children.Add(rec.myrectmember); <-- add member which is actually a rectangle  
Akash Kava
Thanks, that was just a typo on the question..
david
+1  A: 

Define "wrapper"... Does it inherit from Rectangle or some other UIElement? The signature of Canvas.Children.Add requires something that derives from UIElement because it is a UIElementCollection.

You would have to derive from UIElement, or a container UIElement such as Panel so you can add child objects such as a Rectangle.

 public class MyRectangle : Panel
    {
        public MyRectangle()
        {
            this.Children.Add(new System.Windows.Shapes.Rectangle());
        }
    }

Edit:

You need to add your visual elements into the visual tree. Simply making them members of your class won't do. The xaml parser needs to know which members to add to the visual tree.

Use the panel class which is a good starting point. It marks the class with the ContentProperty Attribute:

[ContentProperty("Children", true)] 

// Summary:
//     Specifies which property of a class can be interpreted to be the content
//     property when the class is parsed by a XAML processor.

if you just derive from Panel you gain that functionality. Then anything you want rendered in the visual tree you can just add to the "Children" property of your class.

Or you could implement your own UIElementCollection and flag your class with the attribute

[ContentProperty("Children", true)] 
public class MyRectangle : UIElement
{
     public MyRectangle()
     {
          this.Children = new UIElementCollection();
          this.Children.Add(new System.Windows.Shapes.Rectangle());
     }

     public UIElementCollection Children {get; private set;}
}

One more edit:

Then you also need to construct an instance of your rectangle and add it to the visual tree of your app. So your previous code would do:

MyRectangle rec = new MyRectangle();     
canvas.Children.Add(rec); 

Edit: Just tried to compile this and noticed you can't derive from UIElement... Try FrameworkElement or Control.

Brian Rudolph
so if you create a class that contains a rectangle among other things how do you make it so it derives from UIElement?
david
edited my post to show you
Brian Rudolph
I got the first part.. so even by doing that the XAML won't know how to handle my object?
david
edited again for your benefit. In order the the xaml parser to display an object, it must derive from UIElement which provides it the necessary information to display. http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx
Brian Rudolph
lots of stuff to learn, thanks for your help.
david
no problem, good luck
Brian Rudolph
one more question why is the set private on: UIElementCollection Children {get; private set;}I'm getting an error on it.. The accessibility modifier of the accessor must be more restrictive than the property or indexer
david
edited to fix it. It was set to private so that noone outside of the MyRectangle could reset the collection to null or anything else. The real solution was to set the property to be public.
Brian Rudolph
A: 

Your myRectangle class must inherit from a UIElement (or subclass of it, ie Shape). You can't inherit directly from Rectangle because it is sealed.

Mark H
A: 

You need to extend UIElement for your class to be able to be child to a Canvas. If you just want to wrap one Rectangle in it extend ContentControl and assign the Content property to it:

public class MyRectangle : ContentControl
{
    private Rectangle recNewColor;
    public MyRectangle()
    {
        ///...
        this.Content = recNewColor;
    }
}
Ozan