Rob Smyth

Sunday 1 June 2008

Programmatic Pane Nesting Using DockPanel Suite

I've blogged before on DockPanel Suite and I'm using this framework in my VicFireReader project. In the last week I've had a need to programmatically split the right pane vertically so that I have a top right pane and a bottom right pane as shown in the picture. The code fragment below shows how it was done. 'contentPanel3' is docked to the bottom right.


public MDIParent()
{
InitializeComponent();

DockPanel dockPanel = new DockPanel();
dockPanel.Dock = DockStyle.Fill;
dockPanel.BackColor = Color.Beige;
Controls.Add(dockPanel);
dockPanel.BringToFront();

DockContent content1 = GetDockContentForm("Content 1", DockState.Document, Color.SteelBlue);
content1.Show(dockPanel);

DockContent content2 = GetDockContentForm("Content 2", DockState.DockRight, Color.DarkSeaGreen);
content2.Show(dockPanel);

DockContent content3 = GetDockContentForm("Content 3", DockState.Float, Color.PaleGoldenrod);
content3.Show(dockPanel);
content3.DockHandler.FloatPane.DockTo(dockPanel.DockWindows[DockState.DockRight]);
}

private DockContent GetDockContentForm(string name, DockState showHint, Color backColour)
{
DockContent content1 = new DockContent();
content1.Name = name;
content1.TabText = name;
content1.Text = name;
content1.ShowHint = showHint;
content1.BackColor = backColour;
return content1;
}

8 comments:

Greg said...

Hey Rob this looks like pretty standard UI code and there is often a lot of discussion around unit testing UI code (how it's done and if it should be done).

Did you put any unit tests round this code?

I see you have at least one private method which makes it difficult for unit tests to get to.

Rob Smyth said...

Hi James,

The code fragment thatt you see on the blog was put together specifically for the post. Not unit tested. But, the production code that this fragment derives from was done TDD.

The first thing done when writing the production code was to decouple the third part tools, in this case the docking framework and the .Net framework, using wrappers. (Most of my .Net wrapper can be found on my NoeticTools google codeproject http://code.google.com/p/noetictools/.) Naturally the wrappers are not tested. Using wrappers gives interfaces so that mock objects can be used.

This largley makes the fact that it is UI code irrelevant for TDD. In the production code however anything like background colour etc are done in the controller. (Yes I do TDD these and have found it helpful.) But, if the UI is very simple, I do leave the view (UI class) untested and make sure all logic is in the controller.

The only other thing I can add is that testing via a framework like NUnitForms is not "unit testing" but "integration" or "automated acceptance tests". Both are useful, but only unit tests are part of the TDD coding process.

Rob Smyth said...

Hi James,

In response to your good comment on the private method. Yep, private methods are a smell that another class is required or that a large number of tests may have been missed (if used from multiple public methods).

If the code is written using good TDD discipline (with the refactoring) then private methods only arise as required and are, at least initially, tested. But all bets are off once multiple public methods use the private method.

So, I'm with you, private methods are a smell. But I do use them to make code readable.

Unknown said...

Hi Rob!
I've got a problem recently maybe you could help. When adding DockContent with actif control(3D view) to DockPanel with DockState.Document, 3dView is not displayed. When moving it to other emplacement there is no problem. In Fact the problem seems to be that event OnPaint doesn't occur when dockContent is on DockState.Document. Have you seen this problem before?
Thank you

Anonymous said...

Hi! Thanks for this post. I use VB, and if it would not be an inconvenience, could you make a VB sample? Thanks!

Praves said...

It helped me a lot. Thank you very much

Unknown said...

Im not that good at fuctions but this is a simple conversion to VB.net

Dim dockPanel As New DockPanel
dockPanel.Dock = DockStyle.Fill
dockPanel.BackColor = Color.Beige
Controls.Add(dockPanel)
dockPanel.BringToFront()


Dim content1 As New DockContent
content1.Name = "Content 1"
content1.TabText = "Content 1"
content1.Text = "Content 1"
content1.ShowHint = DockState.Document
content1.BackColor = Color.SteelBlue
content1.Show(dockPanel)

Dim content2 As New DockContent
content2.Name = "Content 2"
content2.TabText = "Content 2"
content2.Text = "Content 2"
content2.ShowHint = DockState.DockRight
content2.BackColor = Color.SteelBlue
content2.Show(dockPanel)

Dim content3 As New DockContent
content3.Name = "Content 3"
content3.TabText = "Content 3"
content3.Text = "Content 3"
content3.ShowHint = DockState.Float
content3.BackColor = Color.PaleGoldenrod
content3.Show(dockPanel)

content3.DockHandler.FloatPane.DockTo(dockPanel.DockWindows(DockState.DockRight))

Unknown said...

hie im not pretty good at functions but this is a simple conversion to VB.net

Dim dockPanel As New DockPanel
dockPanel.Dock = DockStyle.Fill
dockPanel.BackColor = Color.Beige
Controls.Add(dockPanel)
dockPanel.BringToFront()


Dim content1 As New DockContent
content1.Name = "Content 1"
content1.TabText = "Content 1"
content1.Text = "Content 1"
content1.ShowHint = DockState.Document
content1.BackColor = Color.SteelBlue
content1.Show(dockPanel)

Dim content2 As New DockContent
content2.Name = "Content 2"
content2.TabText = "Content 2"
content2.Text = "Content 2"
content2.ShowHint = DockState.DockRight
content2.BackColor = Color.SteelBlue
content2.Show(dockPanel)

Dim content3 As New DockContent
content3.Name = "Content 3"
content3.TabText = "Content 3"
content3.Text = "Content 3"
content3.ShowHint = DockState.Float
content3.BackColor = Color.PaleGoldenrod
content3.Show(dockPanel)

content3.DockHandler.FloatPane.DockTo(dockPanel.DockWindows(DockState.DockRight))