TPF, simple control and layout implementation

4 posts, 1 answers
  1. codicezerouno
    codicezerouno avatar
    22 posts
    Member since:
    Feb 2009

    Posted 06 Feb 2010 Link to this post

    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); 
            } 
        } 
     
  2. Answer
    Dobry Zranchev
    Admin
    Dobry Zranchev avatar
    348 posts

    Posted 08 Feb 2010 Link to this post

    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.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. codicezerouno
    codicezerouno avatar
    22 posts
    Member since:
    Feb 2009

    Posted 08 Feb 2010 Link to this post

    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.
  5. Dobry Zranchev
    Admin
    Dobry Zranchev avatar
    348 posts

    Posted 11 Feb 2010 Link to this post

    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.
Back to Top