Skip to main content

Microsoft Silverlight

Answered Question Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill optionRSS Feed

(0)

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

 I really love the last child fill option of the dockpanel is very usefull. I can think of the stackpanel where the last element is grown until the end of the parent container. I just want to have the opinion of more skilled people in order to have this implementation as easy as possible.

Any tips?

Thx,

Nuno 

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

swildermuth
swildermuth

Star

Star

8320 points

1,546 Posts

Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Do a Google Search.  There was an example at MIX of building a DockPanel that was very straightforward.

(If this has answered your question, "Mark as Answer")

Shawn Wildermuth
C# MVP, MCSD, Speaker and Author

Silverlight 3 Workshop
Miami, FL: Oct 12-14th
Portlant, OR: Dec 2-4th
Atlanta, GA: Dec 7-9th
http://silverlight-tour.com

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

 My search keywords didnt provide any decent result. Can you give me some ideas here?

I was searching by "dock panel silverlight 2 how to"

 Thx,

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

Jabb
Jabb

Member

Member

462 points

81 Posts

Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

I've uploaded my version of the DockPanel at

http://home.comcast.net/~jabbaloo/DockPanel.zip

The biggest weird thing I ran into when trying to put this sample app together is that the DockPanel has to reside in a Silverlight Class Library separate from the main Silverlight Application - if I put the DockPanel.cs code into the main app then the DockPanel.Dock attached property is not recognized. I didn't experience this in my original project because all my custom controls are their own class library.

Anyhoots, hope this helps.

- Jabb
 

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

 I need to try it out. Thx

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi Jabb,

 Thx for showing me your solution. I think i'm running into the same problem here. In blend it works perfectly using the xmlns:prefix:_name:clr-namespace..  notation.

 However, when testing the solution it crashes.

 You said you hadn't any problem because your your controls had their own class library. Can you explain that better?

Thx,

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

Jabb
Jabb

Member

Member

462 points

81 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Make sure that you have something like

xmlns:jabb="clr-namespace:SampleApp;assembly=SampleApp"

instead of 

xmlns:jabb="clr-namespace:SampleApp"

In other words, make sure the assembly is specified - that's why it wasn't working before for me, I didn't have the assembly specified. 

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

 Hi,

I'm not having success in using your code in my testing application.

My first approach was to include the source code on the project, but now i am trying to reference directly your dll. In both cases i forced the import of the dll.

Doesnt work. Gives an exception on the initialize.

Any tips? 

This ist the way i'm importing:

xmlns:jabb="clr-namespace:Jabb.Controls;assembly=Jabb.dll"

Thx,

Nuno 

 

 

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

It was not working because i was putting .dll at the end.

It is working now.

Thx a lot,

Nuno 

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

Your DockPanel seems not to be imposing itself. At least i'm having a strange behaviour from when i use a dock panel inside another:

Imagine this situation:

<UserControl>
  <src:DockPanel LastChildFill="True">
   <src:DockPanel src:DockPanel.Dock="Left" LastChildFill="True" HorizontalAlignment="Center" VerticalAlignment="Stretch">
    <TextBlock src:DockPanel.Dock="Top" Text="ola" HorizontalAlignment="Left" VerticalAlignment="Top" />
   </src:DockPanel>
   <Image src:DockPanel.Dock="Right" Height="Auto" Width="Auto" MinHeight="500" Source="Resources/entrada.jpg" Stretch="UniformToFill" MaxHeight="500" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
  </src:DockPanel>
</UserControl>

 In this case i was expecting that the textblock could be visible and the image would ocuppie the remaining space, however, the image is using all the space and the textblock is completly smashed and there is no room to it.

Do you know this problem?

Does this happens to you?

Thx

Nuno

 

 

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi again,

I've been playing with your DockPanel but i think its not 100% functional.

 It works fine for Dock=Top and Dock=Bottom but it is not working for the cases in which is needed one element in Left and another in Right and another in bottom for example.

I would love to put this class working but i havent completly understand the mechanism of the dock panel and of the measure and arrange override methods.

As i have been reading, measure asks all the children its size, but what is it supposed to return?

And about the arranje? Who tells arranje method the availableSize?

Thx,

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

Jabb
Jabb

Member

Member

462 points

81 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi Nuno,

Sorry I haven't replied, I've been really busy with work the past couple of days.

I've fixed the code and will post here since I don't have time to upload to my site. I'll do that later.

Below are the MeasureOverride and ArrangeOverride methods that have been fixed. I'll try to answer the rest of your questions later.

- jabb

 


protected override Size MeasureOverride(Size availableSize)
{
    if (double.IsInfinity(availableSize.Width) || double.IsInfinity(availableSize.Height))
    {
        availableSize = new Size(0, 0);

        foreach (UIElement child in Children)
            child.Measure(availableSize);

        return availableSize;
    }

    double width = availableSize.Width;
    double height = availableSize.Height;

    foreach (UIElement child in Children)
        if (child.Visibility == Visibility.Visible)
        {
            child.Measure(new Size(width, height));

            switch ((Dock)child.GetValue(DockProperty))
            {
                case Dock.Left:
                case Dock.Right:
                    width = Math.Max(width - child.DesiredSize.Width, 0);
                    break;

                case Dock.Top:
                case Dock.Bottom:
                    height = Math.Max(height - child.DesiredSize.Height, 0);
                    break;
            }
        }

    return new Size(
        Math.Max(0, availableSize.Width - width),
        Math.Max(0, availableSize.Height - height)
        );
}

protected override Size ArrangeOverride(Size finalSize)
{
    double left = 0;
    double top = 0;
    double width = finalSize.Width;
    double height = finalSize.Height;

    UIElement child;

    for (int i = 0; i < Children.Count; i++)
    {
        child = ChildrenIdea;

        if (child.Visibility == Visibility.Visible)
        {
            if (lastChildFill && i == Children.Count - 1)
                child.Arrange(new Rect(left, top, Math.Max(0, width - left), Math.Max(0, height - top)));
            else
                switch ((Dock)child.GetValue(DockProperty))
                {
                    case Dock.Left:
                        child.Arrange(new Rect(left, top, child.DesiredSize.Width, Math.Max(0, height - top)));
                        left += child.DesiredSize.Width;
                        break;

                    case Dock.Top:
                        child.Arrange(new Rect(left, top, Math.Max(0, width - left), child.DesiredSize.Height));
                        top += child.DesiredSize.Height;
                        break;

                    case Dock.Right:
                        width -= child.DesiredSize.Width;
                        child.Arrange(new Rect(Math.Max(0, width), top, child.DesiredSize.Width, Math.Max(0, height - top)));
                        break;

                    case Dock.Bottom:
                        height -= child.DesiredSize.Height;
                        child.Arrange(new Rect(left, Math.Max(0, height), Math.Max(0, width - left), child.DesiredSize.Height));
                        break;
                }
        }
    }

    return finalSize;
}
 

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi Jabb,

I have tried it and the arranjment of the Dock seems to be working now. However, i think there are still problems in the HorizontalAligment and VerticalAlgiment of the dock panel. Those options don't work. I would love to finish this dock panel but stil didnt get how things work very well.

Thx for all your help.

Best regards, 

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal

sinosoidal
sinosoidal

Member

Member

664 points

373 Posts

Answered Question

Re: Re: Is there a way of easily create a dockpanel taking as base a stackpanel? Just to have the last child fill option

Hi,

I have been playing with the DockPanel dock and i think i have made some important changes that seem to make the panel work almost perfectly:

protected override Size MeasureOverride(Size availableSize)

{

double width = availableSize.Width;

double height = availableSize.Height;

double totalDesiredWidth = 0;

double totalDesiredHeight = 0;

double lastLeftRightHeight = 0;

double lastTopBottomWidth = 0;foreach (UIElement child in Children)

{

if (child.Visibility != Visibility.Collapsed)

{

child.Measure(new Size(width, height));

switch ((Dock)child.GetValue(DockProperty))

{

case Dock.Left:

case Dock.Right:

if (lastLeftRightHeight < child.DesiredSize.Height)

{

totalDesiredHeight -= lastLeftRightHeight;

totalDesiredHeight += child.DesiredSize.Height;

lastLeftRightHeight = child.DesiredSize.Height;

}

totalDesiredWidth += child.DesiredSize.Width;

break;

case Dock.Top:

case Dock.Bottom:if (lastTopBottomWidth < child.DesiredSize.Width)

{

totalDesiredWidth -= lastTopBottomWidth;

totalDesiredWidth += child.DesiredSize.Width;

lastTopBottomWidth = child.DesiredSize.Width;

}

totalDesiredHeight += child.DesiredSize.Height;

break;

}

}

}

Size result = new Size(Math.Min(availableSize.Width, totalDesiredWidth), Math.Min(availableSize.Height, totalDesiredHeight));

return result;

 

I have been developing always with an original dockpanel to compare and the only case that seems not to be working perfectly is lastchildfill in a complex situation

 Check it out,

Best regards,

Nuno

--

Imagining (and touching) the future
http://www.nunosantos.net/
http://www.myspace.com/sinosoidal
  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities