tags:

views:

212

answers:

5

In WinForms it was relatively easy to swap out Panels at runtime for other panels. In WPF this seems to be rather more complex (especially from XAML).

Can anyone provide clear guidance on the 'best practice' way of swapping gui elements at runtime (think pages in a wizard type situation).

Many thanks.

A: 

A couple options come to mind. If you create your components as UserControls, and make use of Data Binding, then you should be able to do what you need with minimal fuss.

Option one is to load each component into your parent container (grid, canvas, whatever) with Visibility="Collapsed", and then show and hide them as needed. This has the advantage that you can do this declaratively in XAML.

The other option is to load the components as you need them, so in the event handler of a button, or some other UI element. In this case you would probably want to remove the current displaying item from the Children collection of your host component, and then instantiate your next control, set the DataContext (this is why binding is important), and add it to the Children collection.

(disclaimer: this is based on my experience doing basically what you are asking in Silverlight 3.0, so there may be some WPF quirks I am unaware of).

ckramer
+1  A: 

This can be approached in XAML using datatemplates and/or triggers. For example, if each page in your wizard were represented in an underlying model as a separate class or object, you could use one of the following two options... Both use a ContentControl, which is the perfect control for when the content will vary greatly between different views of the same data.

Please note that the bindings are intended as pseudocode examples, just to convey intent!

DataTemplate-based, using different classes for each page:

<Grid>
  <Grid.Resources>
     <DataTemplate TargetType="{x:Type WizardPageOne}">
        <!-- page 1 layout here -->
     </DataTemplate>
     <DataTemplate TargetType="{x:Type WizardPageTwo}">
        <!-- page 2 layout here -->
     </DataTemplate>
     <!-- ... etc -->
  </Grid.Resources>

  <ContentControl Content="{Binding CurrentPageModel, Source=Wizardmodel}" />
</Grid>

Or Trigger based, using a property that indicates the current page:

<ContentControl Content="{Binding WizardModel}">
    <ContentControl.Style>
       <Style>
           <Style.Triggers>
               <DataTrigger Binding="{Binding CurrentPageIndex} Value="1">
                  <Setter Property="Template">
                      <Setter.Value>
                         <ControlTemplate>
                             <!-- page 1 layout here -->
                         </ControlTemplate>
                      </Setter.Value>
                  </Setter>
               </DataTrigger>
               <DataTrigger Binding="{Binding CurrentPageIndex} Value="2">
                  <Setter Property="Template">
                      <Setter.Value>
                         <ControlTemplate>
                             <!-- page 2 layout here -->
                         </ControlTemplate>
                      </Setter.Value>
                  </Setter>
               </DataTrigger>
               <!-- .... etc -->
           </Style.Triggers>
       </Style>
    </ContentControl.Style>
</ContentControl>

Both options will only load the control for each page as it's required, so you don't have all of the controls "loaded but hidden" in the window.

Dan Puzey
I should also have mentioned that the content of those templates can (arguable *should*) be refactored out to separate resources and/or files, which also keeps your markup shorter and tidier.
Dan Puzey
Thanks. This is very interesting to me. Only snag is I can't see how to animate the transitions.Still, the more general case of dynamically changing UI elements remains open...
Duncan
A: 

The underlying concepts of WinFomrs and WPF is different. In WPF it is not advisable to play around with UIElements(Controls) directly. Make use of DataBinding/DataContexts and just operate on the data and then the UI will function accordingly. This concept is all about WPF MVVM pattern. You can look in to some MVVM samples and try it before doing more complex WPF projects.

A simple example, Suppose you need to dynamically disply a number of items in a ListBox, The typical winform way to do this is to create Items and add directly to the ListBox. But in WPF you create an ObservableCollection<Customer> and bind that to the ListBox.ItemsSource. then define a DataTemplate for Customer Data Type, this ensure the WPF system to understand how a Collection of Customers being displayed in the application. So when you add a new customer instance to the collection, magically your ListBox will get updated with one more item. Seems pretty straight forward and a very loosely coupled way of Data and View right?. Best wishes on your WPF learning. -

http://www.bing.com/search?q=WPF+MVVM

So the high level clue to your question is, make the View appropriately for the Data and when Data/Property Change happens, WPF will take care of changing the Panels/Controls. So it is really simple than WinForms way when you approach from the Data and View perceptive.

Jobi Joy
Thanks, mvvm was the keyword I needed to get started on some good searching. I still don't have animated transitions fully grasped but I am happy to say things are finally making more sense.
Duncan
A: 

The MVVM suggestions here are all good. But if you're designing a page-oriented UI that needs to be navigable, you can use Structured Navigation, too.

Robert Rossney
A: 

I got no idea if this is considered good practice, but what we did on one of our project is quite simple. We defined panels that were all on top of each other and would simply set the visibility to either hidden or visible when it was needed.

David Brunelle
Not at all a good practice to keep the entire visual in the VisualTree all the time. WPF will be more fun and fast if you do with DataTemplate way of invoking another visual(UserControl)
Jobi Joy