I’m very new to WPF and am writing an application using this example as a starting point
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090025
I will only have one workspace visible at any one time, so I want to get rid of the TabControl and use something simple instead – probably a ContentControl, I’m really not sure but all it needs to do is have content in and be closable. So I am trying to replace this:
<DataTemplate x:Key="WorkspacesTemplate"><TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
with:
<DataTemplate x:Key="WorkspacesTemplate">
<ContentControl Content="{Binding ??}" ContentTemplate="{StaticResource ClosableTabItemTemplate}"/>
</DataTemplate>
but I don’t know what to bind to. The code in the example seems to use CollectionViewSource to set the active workspace – it’s the active workspace that I am interested in but I don’t understand what TabControl is doing except that it’s something to do with IsSynchronizedWithCurrentItem=”True”
The template is invoked from here (Workspaces is the ObservableCollection of ViewModels):
<HeaderedContentControl Content="{Binding Path=Workspaces}" ContentTemplate="{StaticResource WorkspacesTemplate}" Header="Workspaces" Style="{StaticResource MainHCCStyle}"/>
and here is the ClosableItem template:
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel Width="120">
<Button
Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Courier"
FontSize="9"
FontWeight="Bold"
Margin="0,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16" Height="16"
/>
<ContentPresenter
Content="{Binding Path=DisplayName}"
VerticalAlignment="Center"
/>
</DockPanel>
</DataTemplate>
Please can someone explain what I need to do? Thanks
The
WorkspacesTemplateis telling WPF how to display theWorkspacesproperty, which, as you say is anObservableCollectionof ViewModels.So, the
WorkspacesTemplatesays, display all these ViewModels in a tab control, and for each ViewModel, use theClosableTabItemTemplateto display the ViewModel in a tab.Since you only want one workspace visible at a time, you don’t need to expose a collection of workspaces from your ViewModel, and you don’t need a tab control to display them. You simply expose the one current workspace from your ViewModel and provide some XAML to display it.
If you still want to use a template to wrap the ViewModel, then yes, you can just use a
ContentControlto invoke the template:and to invoke the template
However, if this is the only place that the XAML is going to be used, you might as well forget the template and just declare the XAML directly. Eg, (instead of ContentControl)
EDITED TO ADD:
I think you might be getting confused because currently the ViewModel has no concept of the “Selected Workspace”, it just exposes a collection. For completeness (but don’t worry about all this), the selection is introduced by the
TabControlwhich indirectly uses the defaultCollectionViewfor theWorkspacescollection, andCollectionViewhas the concept of a selected item. This is all in the view.I wouldn’t worry about any of this now, just expose the one workspace yourself from your ViewModel.
EDIT2:
Your close button is appearing because you are explicitly setting a
ContentTemplateon yourHeaderedContentControl. This template will appear regardless ofContent.To make a template only appear when there is data in
Content, make the template implicit instead. If you add aDataTypeto your template definition (and remove the key), you tell WPF to always use this template to display an object of that data type.Then you can remove the explicit template from your
HeaderedContentControl. Simply setting theContentwill be enough to invoke the template, and if there is no Content, there is no template.(ps. If you’re not using the header of
HeaderedContentControl, you might as well just use a bog standardContentControl)