This is a migrated thread and some comments may be shown as answers.

TPF, simple control and layout implementation

3 Answers 74 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
codicezerouno
Top achievements
Rank 1
codicezerouno asked on 06 Feb 2010, 11:19 AM
Hi,
I'm getting into TPF based control development and I'm finding a lot of difficulties to understand the behind logic maybe because there is not enough documentation and examples on that.

I'm trying to make a control that arrange in a stacklayout many radlabelelement as the Rows property value of my control; the height of any child element should be control.Size.Height/control.Rows, so I got my child to have same height.

This is the way I implement it, could you please help me on that?

MyControl:
    public class MyControl : RadControl 
    { 
        MyElementPanel elementPanel; 
 
        public MyControl() 
        { 
            this.UseNewLayoutSystem = true
            this.AutoSize = true
        } 
 
        protected override void CreateChildItems(RadElement parent) 
        { 
            elementPanel = new MyElementPanel(); 
            this.RootElement.Children.Add(elementPanel); 
            base.CreateChildItems(parent); 
        } 
 
        public int Rows 
        { 
            get 
            { 
                return this.elementPanel.Rows; 
            } 
            set 
            { 
                this.elementPanel.Rows = value; 
            } 
        } 
 
    } 
 

MyElement:
    public class MyElementPanel : RadItem 
    { 
        StackLayoutPanel layout; 
 
        public static RadProperty RowsProperty = RadProperty.Register( 
            "Rows"
            typeof(int), 
            typeof(MyElementPanel), 
            new RadElementPropertyMetadata(2, ElementPropertyOptions.AffectsLayout)); 
 
        public int Rows 
        { 
            get 
            { 
                return (int)this.GetValue(RowsProperty); 
            } 
            set 
            { 
                this.SetValue(RowsProperty, value); 
            } 
        } 
 
        protected override void CreateChildElements() 
        { 
            var border = new BorderPrimitive(); 
            Children.Add(border); 
            var background = new FillPrimitive(); 
            Children.Add(background); 
 
            layout = new StackLayoutPanel(); 
            layout.Orientation = System.Windows.Forms.Orientation.Vertical; 
            this.Children.Add(layout); 
 
            var rows = this.Rows; 
            int rowHeight = (int)this.Size.Height / rows; 
            for (int i = 0; i < rows; i++) 
            { 
                var child = new RadLabelElement(); 
                child.Text = (i + 1).ToString(); 
                child.Margin = new System.Windows.Forms.Padding(1); 
                child.Children[2].AutoSize = false
                child.Children[2].Size = new Size(20, rowHeight); 
                child.BorderVisible = true
                layout.Children.Add(child); 
            } 
 
            base.CreateChildElements(); 
        } 
 
        protected override void OnPropertyChanged(RadPropertyChangedEventArgs e) 
        { 
            if (e.Property == StorageRackElement.RowsProperty) 
            { 
                var rows = (int)e.NewValue; 
                int rowHeight = (int)this.Size.Height / rows; 
                layout.Children.Clear(); 
                for (int i = 0; i < rows; i++) 
                { 
                    var child = new RadLabelElement(); 
                    child.Text = (i + 1).ToString(); 
                    child.Margin = new System.Windows.Forms.Padding(1); 
                    child.Children[2].AutoSize = false
                    child.Children[2].Size = new Size(20, rowHeight); 
                    child.BorderVisible = true
                    layout.Children.Add(child); 
                } 
            } 
            if (e.Property == StorageRackElement.BoundsProperty) 
            { 
                int rowHeight = (int)this.Size.Height / this.Rows; 
                foreach(var child in layout.Children) 
                    child.Children[2].Size = new Size(20, rowHeight); 
            } 
 
            base.OnPropertyChanged(e); 
        } 
    } 
 

3 Answers, 1 is accepted

Sort by
0
Accepted
Dobry Zranchev
Telerik team
answered on 08 Feb 2010, 02:19 PM
Hello Stefano Cadò,

Thanks for your question. You should use CreateChildElements method only for the creation of elements. In your case you should use the following code:

protected override void CreateChildElements()
{
    var border = new BorderPrimitive();
    Children.Add(border);
    var background = new FillPrimitive();
    Children.Add(background);
 
    int rows = this.Rows;
    for (int i = 0; i < rows; i++)
    {
        var child = new RadLabelElement();
        child.Text = (i + 1).ToString();
        child.Margin = new System.Windows.Forms.Padding(1);
        child.BorderVisible = true;
        this.Children.Add(child);
    }
 
    base.CreateChildElements();
}

If you want to calculate the sizes of the elements you should override MeasureOverride method and calculate the size as you wish. The method takes a parameter of type SizeF that represents the size of the control that contains that element:

protected override SizeF MeasureOverride(SizeF availableSize)
{
    int count = this.Children.Count;
    int rows = this.Rows;
    int height = (int)(availableSize.Height / (count - rows));
    for (int i = 2; i < rows; i++)
    {
        RadLabelElement labelElement = this.Children[i] as RadLabelElement;
        if (labelElement == null)
            continue;
 
        labelElement.Measure( new SizeF(availableSize.Width, height) );
    }          
 
    return availableSize;
}

You should do the arrangement of elements in the ArrangeOverride. Here you decide where each element must be visualized. The example below demonstrates how to arrange your elements. The ordered matters e.g. the last element will may hide the first one if they share visual estate:

protected override SizeF ArrangeOverride(SizeF finalSize)
{
    int count = this.Children.Count;
    int rows = this.Rows;
    int height = (int)(finalSize.Height / (count - rows));
    int y = 0;
    for (int i = 2; i < rows; i++)
    {
        RadLabelElement labelElement = this.Children[i] as RadLabelElement;
        if (labelElement == null)
            continue;
 
        labelElement.Arrange(new RectangleF(0, y * height, finalSize.Width, height));
        y++;
    }
    return finalSize;
}

If you have additional questions feel free to ask.

Regards,
Dobry Zranchev
the Telerik team

Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Follow the status of features or bugs in PITS and vote for them to affect their priority.
0
codicezerouno
Top achievements
Rank 1
answered on 08 Feb 2010, 05:15 PM
Thank you Dobry. Now it's more clear.

A question about performance. I see that resizing is slow, not only while designing: I mean, I have 5*30  childs, for example, arranged in a table layout (my table layout) and while resizing in design mode (the control container) it takes a lot.

Can you suggest me something and guide me throw the right way to get the maximum from TPF? If you need I will provide you the code.

Regards, Stefano.
0
Dobry Zranchev
Telerik team
answered on 11 Feb 2010, 09:42 AM
Hi Stefano Cadò,

Thank you for your questions. Indeed sending us your code will be very helpful in fine-tuning your application. We will try to minimize refreshes if that's possible.

Sincerely yours,
Dobry Zranchev
the Telerik team

Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Follow the status of features or bugs in PITS and vote for them to affect their priority.
Tags
General Discussions
Asked by
codicezerouno
Top achievements
Rank 1
Answers by
Dobry Zranchev
Telerik team
codicezerouno
Top achievements
Rank 1
Share this question
or