Wpf design ; multiple views in one window

26,180

If you use WPF, use ContainerControl or ContentPresenter for that.

In general, "switching Visibility On/Off" is not a good way to go. It forces the UI to create all objects, even those invisible ones, and to handle their data and events, etc.

And you need to switch it all manually.

WPF provides you with many mechanisms that can save you this. Some are smarter than others, some not.

One of the most basic mechanism in WPF is the Control and its Template property. You can replace whole your Grid+Contents+SwitchingVisibility idea with a single Control and switching its Template:

<Window.Resources>
    <ControlTemplate x:Key="panel1"> ..carrots.. </ControlTemplate>
    <ControlTemplate x:Key="panel2"> ..cucubers.. </ControlTemplate>
    <ControlTemplate x:Key="panel3"> ..donkey.. </ControlTemplate>
    ...
</Window.Resources>

<Grid x:Name="LayoutRoot">
    <Control x:Name="foo" />
</Grid>

Now, if you get the foo and set its .Template and set it to panel1, then the "carrots" will show up. if you set it to panel3, donkeys. And so on.

It's very powerful, but it will not be really handy due to some other things I won't cover. There are books and tutorials that explain Templates in depth. Also, this mechanism is really not designed for such task. It's the most basic one, and a good thing to know if you want to work in WPF, but there are more suitable ones here.

Second next powerful and still basic mechanism is ContentControl/ContentPresenter. They work almost in the same way (actually CC uses CP internally), so I'll skip it.

ContentControl is a smart control that knows how to automatically select a correct Template with respect to the data you are tryng to present.

So:

<Window.Resources>
    <DataTemplate DataType="CarrotData"> ..carrots.. </..>
    <DataTemplate DataType="CucumberData"> ..cucubers.. </..>
    <DataTemplate DataType="DonkeyData"> ..donkey.. </..>
    ...
</Window.Resources>

<Grid x:Name="LayoutRoot">
    <ContentControl x:Name="foo" Content="{Binding ..}" />
</Grid>

Note the change from 'ControlTemplate' to 'DataTemplate'.
Now, with this setting, you don't even need to switch templates manually. You just get the "foo" and set its Content to either:

  • a CarrotData object, that contains the carrot-related data
  • a CucumberData object, that contains the cucumber-related data
  • a DonkeyData object, that contains the donkey-related data

Once you set the data to be shown (i.e. foo.Content = carrots[5]), the ContentControl will pick the relevant template to be shown.

You can bind the Content property to just about anything. If you have some dataclass that contains carrots/donkeys and has a property CurrentThing, you can bind to it and ContentControll will switch the views automatically along with the changes to CurrentThing.

That's basics. There's much more to it, in almost any point I tried to briefly cover. For now, leave ControlTemplates. Read about DataTemplates and Bindings. Read about ContentPresenter (shows 1 template for 1 item) and ItemsControl (shows N items+templates). Then, read a little on MVVM pattern.

You will quickly see that "having everything in one Grid" and "switching Visibility" is an odd way to do it.

However, I wouldn't be fair if I didn't mention that everything has a cost included. Extensive use of templates and bindings makes your app a bit slower compared to what you could get when you do everything manually. But usually, doing it manually is just not really worth it.

Share:
26,180
rollekn
Author by

rollekn

Updated on January 06, 2020

Comments

  • rollekn
    rollekn over 4 years

    Im building an application where I want to head for a design, that could remind of a dockpanel.

    What I want, is having buttons in the left side (or left panel) representing different areas of the application (e.g "Milk", "Bread") and then have different "views" in the middle-panel.

    What I already have tried, is making an application with a "Frontpage", and buttons changing the whole window/usercontrol - this however will not give me static areas/panels.

    I do not want to use a tabcontrol with the tabtitemstrip being vertical - however it is kinda the same functionality im looking to have.

    Any ideas?

    Below is a picture with the wished design, to kinda give an idea of my thoughts.. Any help appreciated :)

    http://s57.photobucket.com/user/RolleKn/media/wpfdesign_zps3737b014.jpg.html