0

I need to design a form with a treeview in the left and a container for some other control in the remaining area. Whenever user selects an item in the treeview some custom control appears on the right. For example, let's say that the treeview contains values "Audio settings" and "Video settings", and I have two controls that can be bound to these settings and I want to display them on the form when needed.

Now, from what I've read about MVVM, I shouldn't have properties that will return UserControls or DataTemplates, am I right? It will be messing with "VM shouldn't know implementation details of the view" as I see it. So, how do I handle this situation properly in terms of MVVM? Should I maybe use converters for this and if so, how would it look?

I can't provide any code at the moment (mostly because there isn't any), but I will try to clarify the problem if needed. Thanks in advance.

Dyppl
  • 12,161
  • 9
  • 47
  • 68

2 Answers2

2

This is where the WPF templating system helps out.

The main idea is to have a ContentControl display the appropriate view depending on the selected value in the TreeView.

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
    <DockPanel>

        <ListBox DockPanel.Dock="Left" ItemsSource="{Binding Editors}" SelectedItem="{Binding SelectedEditor}" />

        <ContentControl Content="{Binding SelectedEditor}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type l:VideoViewModel}">
                    <l:VideoView />
                </DataTemplate>
                <DataTemplate DataType="{x:Type l:AudioViewModel}">
                    <l:AudioView />
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>

    </DockPanel>
</Window>

AudioView and VideoView are UserControls.

As you can see, the ContentControl's content is bound to the SelectedEditor property in the ViewModel, which is also bound to the SelectedItem of the Listbox.

So the ViewModel for the main view looks like this.

public class MainWindowViewModel : INotifyPropertyChanged
{
    public IEnumerable<object> Editors
    {
        get
        {
            yield return new VideoViewModel();
            yield return new AudioViewModel();
        }
    }

    private object selectedEditor;
    public object SelectedEditor
    {
        get { return selectedEditor; }
        set
        {
            if (selectedEditor == value)
                return;
            selectedEditor = value;
            OnPropertyChanged("SelectedEditor");
        }
    }
}

So you can see that the main ViewModel has no GUI data in it.

To handle hooking up a TreeView to a SelectedItem property in a ViewModel see Data binding to SelectedItem in a WPF Treeview

Community
  • 1
  • 1
Cameron MacFarland
  • 70,676
  • 20
  • 104
  • 133
  • Thanks, that looks good. I actually googled similar solution for tabpages yesterday and I'll give it a try. – Dyppl Feb 15 '11 at 04:54
  • Btw, do you have any idea if this will work (maybe with some tuning) in Silverlight? – Dyppl Feb 15 '11 at 04:55
  • Err, should do. I've never done any Silverlight work, but it does have the DataTemplate system, which is all this really needs to work. – Cameron MacFarland Feb 15 '11 at 05:21
1

You can implement it throw two properties: ShowAudioSettings and ShowVideoSettings in ViewModel and bind it on Visibility of your controls.

Also, you can make it with VisualStateManager.

Rover
  • 2,203
  • 3
  • 24
  • 44
  • Is VSM WPF4-only? I'm afraid it will be .NET 3.5 for this project – Dyppl Feb 14 '11 at 10:35
  • VSM is not WPF4 only. In 3.5 you can use it, but only for UserControls, cause VisualStateManager.GoToState implemented only for Control, so you can't use it for changing states of Panel or other FrameworkElement. – Rover Feb 14 '11 at 10:38