One ViewModel two Views with MVVMLight in WPF - c#

The datacontext's are configured in App.xaml (with MVVMLight), but when is one ViewModel one View.
<DataTemplate DataType="{x:Type vm:VMUserControl}">
<views:UCViewSnow />
</DataTemplate>
I need use the same ViewModel with multiples Views, i added DataContext in codebehind for each View (.xaml.cs) but not working.
DataContext = ViewModel.ViewModelLocator.GetStaticVMuserControl;
I need to add DataContext according to parameters from app.config.
I use WPF with framework 4.5.1 with MVVM light from nuget in VS 2015
<DataTemplate DataType="{x:Type vm:VMUserControl}">
<views:UCViewDark />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:VMUserControl}">
<views:UCViewSnow/>
</DataTemplate>

I see couple potential reasons why DataTemplate can didn't work.
1st - probably you didn't bind Content property of your view with your DataContext (vm:VMUserControl).
2nd - you use custom template of content control without ContentPresenter.
For example:
App.xaml
...
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>
...
In your View
Update:
In case if you define two datatemplate for one DataType (viewmodel)
you additional should implement and use own ContentTemplateSelector.
<View ...
DataSource={Binding Source={StaticResource Locator}, Path=YourViewModel}>
<View.Resource>
<ResourceDictionar>
<DataTemplate DataType="{x:Type vm:VMUserControl}"
x:Key="darkDataTemplate">
<views:UCViewDark />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:VMUserControl}"
x:Key="snowDataTemplate">
<views:UCViewSnow/>
</DataTemplate>
<local:CustomContentTemplateSelector x:Key="yourContentTemplateSelector"
FirstDataTemplate={StaticResource snowDataTemplate}
SecondDataTemplate={StaticResource darkDataTemplate} />
</ResourceDictionar>
</View.Resource>
<ContentControl Content={Binding}
ContentTemplateSelector={StaticResource yourContentTemplateSelector}/>
CustomContentTemplateSelector.cs
public class CustomContentTemplateSelector:DataTemplateSelector
{
public DataTemplate FirstDataTemplate {get; set;}
public DataTemplate SecondDataTemplate {get; set;}
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container){
// here you should impelement logic for choose data template
// if (condition)
// return FirstDataTemplate
// else
// return SecondDataTemplate
}
}

Related

c# mvvm bind views to tabcontrol with header

I have a wpf programme with a main View (Window)which contains a TabControl to show several different UserControl Views (the sub-views, one in each tab). Every View has an associated ViewModel.
I wish to bind the TabControl so that I just need to load a new sub-view into the ApplicationViewModel and it will appear on the TabControl.
I have successfully bound the sub-views to the content, but cannot seem to get anything in the header. I wish to bind the header to a property in the sub-view's ViewModel, specifically TabTitle.
Application View (DataTemplate binding not working):
<Window ...>
<DockPanel>
<TabControl ItemsSource="{Binding PageViews}" SelectedIndex="0"> <!--Working-->
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataContext.TabTitle}, Path=DataContext.TabTitle}" /> <!--Not Working-->
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</DockPanel>
</Window>
Application ViewModel (ObservableObject basically implements INotifyPropertyChanged`):
class ApplicationViewModel : ObservableObject
{
private DataManager Data;
private ObservableCollection<UserControl> _pageViews;
internal ApplicationViewModel()
{
Data = new DataManager();
PageViews.Add(new Views.MembersView(new MembersViewModel(Data.DataSet)));
}
public ObservableCollection<UserControl> PageViews
{
get
{
if (_pageViews == null)
{
_pageViews = new ObservableCollection<UserControl>();
}
return _pageViews;
}
}
The MembersView Code behind:
public partial class MembersView : UserControl
{
public MembersView(MembersViewModel ViewModel)
{
InitializeComponent();
DataContext = ViewModel;
}
}
MembersViewModel (truncated):
public class MembersViewModel : INotifyPropertyChanged
{
public TabTitle { get; protected set; }
public MembersViewModel(DataSet BBDataSet)
{
TabTitle = "Members";
}
//All view properties
}
I'm sure that it is something simple...
You are binding the TabControl to a collection of type UserControl. That means the data context for each item will be of type UserControl. There is no property named "TabTitle" in UserControl, so the binding will not work.
I think what you are trying to do can be accomplished with the following changes:
Have ApplicationViewModel expose a collection of type MembersViewModel, instead of UserControl, and populate it appropriately.
Setup a ContentTemplate to create views for your items in the TabControl:
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type namespace:MembersViewModel}">
<namespace:MembersView />
</DataTemplate>
</TabControl.ContentTemplate>
(Replace "namespace:" with your xaml imported namespace containing your controls.)
Update the ItemTemplate in your TabControl so it binds properly to the view model:
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabTitle}}" />
</DataTemplate>
</TabControl.ItemTemplate>
Update MembersView to have a parameterless constructor. The DataContext on the view will be set for you by the TabControl. If you need to access the view model from your code-behind, it should be available through the DataContext property after the InitializeComponent() call.
Anytime you are working with ItemsControl (and its extensions such as ListBox, TreeView, TabControl, etc.), you should never be instantiating your own item views. You always want to setup a template that instantiates the view based on the data (or view model) and bind directly to the data (or view model) in the ItemsSource property. This allows all of the item's data contexts to be setup for you so you can bind to them.
Edit: Since you have multiple view / viewmodel pairings, you will want to define your templates slightly differently:
<TabControl ItemsSource="{Binding PageViews}" SelectedIndex="0">
<TabControl.Resources>
<DataTemplate DataType="{x:Type namespace:MembersViewModel}">
<namespace:MembersView />
</DataTemplate>
<DataTemplate DataType="{x:Type namespace:ClassesViewModel}">
<namespace:ClassesView />
</DataTemplate>
<DataTemplate DataType="{x:Type namespace:SessionsViewModel}">
<namespace:SessionsView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabTitle}}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
The difference is that you want to define multiple data templates, one for each type, in your resources. That means it will use those templates each time it encounters those types. You still want to set ItemTemplate to force the tab headers to use a specific template. However, do not set ContentTemplate, allowing the content to use the data templates defined in resources.
I hope that makes sense.
P.S. You can also define these data templates in a higher level resource dictionary, such as in your main window or your application, if you want them to apply to content presenters every place you use those view models, rather than only in this one TabControl.

Best way to bind a set of same-type ViewModels to a TabControl in MVVM / WPF

I have an existing ViewModel and View in an MVVM project. Effectively this View presents a collection of items in a particular, styled way. I'll call this existing ViewModel "CollectionPresenter".
Up to now, this has been presented as as follows in XAML:
<Grid>
<ns:CollectionPresenter />
</Grid>
Now, I want to have a dynamic collection of these "CollectionPresenter" view models made available ideally in a tab view.
My approach has been to define an observable collection of these "CollectionPresenters", creating them first on construction of the parent view model. The XAML above then changed to look something like this:
<TabControl ItemsSource="{TemplateBinding CollectionPresenters}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding CollectionPresenterTitle}">
</DataTemplate>
<TabControl.ItemTemplate>
<TabControl.ContentTemplate>
... this is where things get confusing
</TabControl.ContentTemplate>
<TabControl>
You can see above my problem is the ContentTemplate.
When I load this up, I get a tab control and it has as many tabs as my observable collection of "CollectionPresenter" objects.
However, the content of the tab control is always empty.
Is this approach correct - and is there a better way regardless?
EDIT: ADDING SOME EXTRA THINGS TO MAKE IT CLEARER
I've tried the below, but it doesn't work. The XAML with the Tab Control (the binding to "Things" works fine):
<TabControl ItemsSource="{TemplateBinding Things}">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewModels:Thing}">
<TextBlock Text="{Binding ThingName}" Width="200" Background="Blue" Foreground="White"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type viewModels:Thing}">
<TextBlock Text="{Binding ThingName}" Width="500" Height="500" Background="Blue" Foreground="White"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
The definition for the "Things" observable collection (which is inside the templated parent (ParentObject) of the XAML with the tab control):
public static readonly DependencyProperty ThingsProperty =
DependencyProperty.Register("Things", typeof(ObservableCollection<Thing>), typeof(ParentObject), new PropertyMetadata(null));
public ObservableCollection<Thing> Things
{
get { return (ObservableCollection<Thing>)GetValue(ThingsProperty); }
set { SetValue(ThingsProperty, value); }
}
Stripped down version of the "Thing" view model:
public class Thing : ViewModelBase
{
public Thing()
{
}
public void Initialise(ObservableCollection<Thing> things, string thingName)
{
Things = things;
ThingName = thingName;
}
public static readonly DependencyProperty ThingNameProperty =
DependencyProperty.Register("ThingName", typeof(string), typeof(Thing), new PropertyMetadata(null));
public string ThingName
{
get { return (string)GetValue(ThingNameProperty); }
set { SetValue(ThingNameProperty, value); }
}
}
Looking at my answer to the WPF MVVM navigate views question, you can see this:
<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
<Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
<Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
<Views:CompanyView />
</DataTemplate>
Now, wherever we use an instance from one of these types in our application, these DataTemplates will tell the framework to display the related view instead.
Therefore, your solution is to simply not hard-code one single DataTemplate to the TabControl.ItemTemplate property, but to leave that blank instead. If you use multiple DataTemplates without providing x:Key values, then they will implicitly be applied when each data object is to be rendered in the TabControl.
UPDATE >>>
Using these DataTemplates should leave your TabControl looking like this:
<TabControl ItemsSource="{TemplateBinding Things}" />
I'm not sure why you're using a TemplateBinding there though as you don't need to define any new templates to get this working... therefore, you should be using a plain old Binding instead.
One other thing that you need to do is to use different data types for each item in the collection that you want to display differently. You could derive custom classes from your Thing class and so the collection could still be of type ObservableCollection<Thing>.

How do I bind an ObservableCollection to an AvalonDock DocumentPaneGroup?

I need to load a collection of items as documents in AvalonDock 2.0. These objects inherit from an abstract class, for which I want to render a frame inside the document depending on which subclass are.
This is my XAML:
<ad:DockingManager Background="Gray" DocumentsSource="{Binding Path=OpenProjects}"
ActiveContent="{Binding Path=CurrentProject, Mode=TwoWay}">
<ad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=OpenProjects/Name}" />
</DataTemplate>
</ad:DockingManager.DocumentHeaderTemplate>
<ad:DockingManager.LayoutItemTemplate>
<DataTemplate>
<Grid>
<Grid.Resources>
<DataTemplate DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</Grid.Resources>
</Grid>
</DataTemplate>
</ad:DockingManager.LayoutItemTemplate>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
So far I've achieved to show as many documents as items are in the OpenProjects collection, but I can't seem to show anything inside each document.
Plus, I don't know if I'm using ActiveContent properly: I want to assign to CurrentProject the ViewModel assigned on the current active document.
Thank you for your time.
The reason why you are not able to see any content is of the way you defined your LayoutItem templates. This can't work.
Also consider to use a custom control instead of the Frame. The Frame is very heavy. Unless you don't need to display HTML, avoid this control. Content navigation is very easy to implement, in case you want to show navigable content. Just wrap your document content into a UserControl.
You are using the ActiveContent property properly.
To fix your problem you have three recommended solutions, where the first doesn't exactly meet your requirements. Since you defined the DockingManager.LayoutItemTemplate wrong, I will show it anyway.
Solution 1: Local LayoutItemTemplate
In case you only need a single template for all LayoutDocument and LayoutAnchorable containers, you can use the DockingManager.LayoutItemTemplate property. This property accepts a single DataTemplate. Nested DataTemplate definitions, like in your code, are generally not supported by WPF.
<ad:DockingManager>
<ad:DockingManager.LayoutItemTemplate>
<DataTemplate>
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
</ad:DockingManager.LayoutItemTemplate>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane />
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
Solution 2: Implicit DataTemplate
In more advanced scenarios you display different views based on different models. If the displayed content depends on the data type of the model alone (like in your case), the recommended approach is to provide implicit DataTemplate definitions.
WPF will automatically apply an implicit DataTemplate to every data type that matches the DataTemplate.TargetType of this template.
The DataTemplate is implicit, if it has no explicit x:Key value assigned. To ensure that the DataTemplate can actually be applied automatically, the DataTemplate must also be defined in the same resource scope as the target type. E.g., defining the DataTemplate in Application.Resources of App.xaml, would make the template to be applied automatically in the application scope.
<ad:DockingManager>
<ad:DockingManager.Resources>
<DataTemplate DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</ad:DockingManager.Resources>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
Solution 3: DataTemplateSelector
The previous solution, which uses implicit DataTemplate definitions, can be replaced with a DataTemplateSelector. DataTemplateSelector is another WPF concept to apply a DataTemplate selectively.
A DataTemplateSelector is the recommended choice, if selecting a DataTemplate may depend on more complex constraints, than the model's data type alone. It allows to e.g. evaluate the data item and chose the appropriate template based on certain criteria.
To define a template selector, you have to extend DataTemplateSelector, which is expected to return a DataTemplate.
The easiest way is to define the templates in App.xaml resource dictionary using an x:Key and then select from them based on the condition.
DockingManger accepts a template selector by assigning the DockingManager.LayoutItemTemplateSelector property:
App.xaml
Define the explicit DataTemplate using x:Key:
<Application.Resources>
<DataTemplate x:Key="SubclassAViewModelTemplate" DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate x:Key="SubclassBViewModelTemplate" DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate x:Key="SubclassCViewModelTemplate" DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</Application.Resources>
DocumentManagerTemplateSelector.cs
The following code uses the Switch Expression, which is available since C# 8.0. It can be replaced with a switch statement or cascaded if-statements.
class DocumentManagerTemplateSelector : DataTemplateSelector
{
#region Overrides of DataTemplateSelector
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return item switch
{
SubclassAViewModel _ => Application.Current.Resources["SubclassAViewModelTemplate"] as DataTemplate,
SubclassBViewModel _ => Application.Current.Resources["SubclassBViewModelTemplate"] as DataTemplate,
SubclassCViewModel _ => Application.Current.Resources["SubclassCViewModelTemplate"] as DataTemplate,
_ => base.SelectTemplate(item, container)
};
}
#endregion
}
MainWindow.xaml
<ad:DockingManager>
<xcad:DockingManager.LayoutItemTemplateSelector>
<local:DocumentManagerTemplateSelector />
</xcad:DockingManager.LayoutItemTemplateSelector>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>

Don't create new view each time with DataTemplate/DataType

I have something like this:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:VM1}">
<!-- View 1 Here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- View 2 here -->
</DataTemplate>
<Window.Resources>
<ContentPresenter Content="{Binding}"/>
</Window>
This will automatically swap out the view as I bind different viewmodels, which is very handy.
However, I have one view with a tabcontrol and many subviews. Each subview has several visual parts that are configured by a custom xml file (complex business case). Each time this view is created, the xml file is parsed which causes a small (1-2 second) delay. It's enough of a delay to be annoying and make the UI feel sluggish.
Is there a way to use the DataTemplate pattern without destroying and recreating the view each time a viewmodel is bound? I'd rather not change the viewmodel if possible.
For this case the easiest solution is to have the two views always there and change which one is visible. You can use a converter to change the visibility based on the type of the data context
<View1 Visibility="{Binding Converter={StaticResource TypeToVisibilityConverter, ConverterParameter=VM1}" />
<View2 Visibility="{Binding Converter={StaticResource TypeToVisibilityConverter, ConverterParameter=VM2}" />
And the converter will check if the type matches with the parameter to return Visible, or Collapsed otherwise.
You could wrap your VM into an additional class. Your DataTemplates will decide on the type of the Wrapper class but the real implementation will be exposer through a property of this Wrapper. When this property will change the DataTemplate wont be reloaded but all the bindings will be refreshed.
Wrapper class:
public class WrapperVM1:INotifyPropertyChanged
{
public Content VM1 { get{...} set{...} }
}
public class WrapperVM2:INotifyPropertyChanged
{
public Content VM2 { get{...} set{...} }
}
Now your data templates will describe wrapper class representations:
<DataTemplate DataType="{x:Type local:WrapperVM1}">
<TextBlock Text={Binding Content.SomPropertyInVM1}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:WrapperVM2}">
<TextBlock Text={Binding Content.SomPropertyInVM2}"/>
</DataTemplate>
As you can see if you substitute the Content property of the wrapper with a new instance of VM this won't recreate the view but all bindings will update. However if you need to switch to other type of VM you will have to substitute the Wrapper class by the appropriate Wrapper.

How to add controls in the tab item programmatically in wpf with MVVM

I have created a tab control and Created the tabItems dynamically, but i dont know how to add controls into the tabItems using MVVM. Could any one help me
There are a few ways to programmatically add Tab Items in WPF and I am going to show you a simple example on how I deal with this in my application.
First I host a collection of the ViewModels for the TabItems (or Workspaces as I refer to them) in my MainWindowViewModel.cs:
private ObservableCollection<WorkspaceViewModel> _workspaces;
public ObservableCollection<WorkspaceViewModel> Workspaces
{
get
{
if (_workspaces == null)
{
_workspaces = new ObservableCollection<WorkspaceViewModel>();
}
return _workspaces;
}
}
Next I add a reference to the various controls in my MainWindow.xaml. This is important as we want to make sure that whenever the collection contains a ViewModel that it displays the appropriate View for that Model.
<Window.Resources>
<DataTemplate DataType="{x:Type vm:MyUserControlViewModel}">
<vw:MyUserControlView/>
</DataTemplate>
</Window.Resources>
If you have multiple types of UserControls you simply add them all here like this:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:FirstUserControlViewModel}">
<vw:FirstUserControlView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondUserControlViewModel}">
<vw:SecondUserControlView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ThirdUserControlViewModel}">
<vw:ThirdUserControlView/>
</DataTemplate>
</Window.Resources>
Next we add the TabControl and bind it to our Workspace Collection.
<TabControl ItemsSource="{Binding Workspaces}"/>
Then I simply add my ViewModels to the Collection to have them show up in the TabControl.
Workspaces.Add(new FirstUserControlViewModel());
Workspaces.Add(new SecondUserControlViewModel());
Workspaces.Add(new ThirdUserControlViewModel());
My WorkspaceViewModel that I base the TabItem collection of is very simple and looks something like this:
public abstract class WorkspaceViewModel : BaseViewModel
{
public String HeaderText { get; set; }
public override string ToString()
{
return HeaderText;
}
}
Adding a TabItem:
To create a TabItem you simply create a UserControl and ViewModel like you normally would using WPF and the MVVM pattern.
namespace MyApplication.ViewModel
{
public class FirstUserControlViewModel : WorkspaceViewModel
{
public FirstUserControlViewModel ()
{
base.HeaderText = "My First Tab";
}
}
}
Next you need to bind a View to your new ViewModel.
<DataTemplate DataType="{x:Type vm:FirstUserControlViewModel }">
<vw:FirstUserControlView/>
</DataTemplate>
Then you create an instance of the ViewModel and add it to the collection in your MainWindowViewModel.
FirstUserControlViewModel firstvm = new FirstUserControlViewModel();
Workspaces.Add(firstvm);
And now the TabItem should show up in your TabControl.
Loading TabItems dynamically using Extensions:
In some cases you might even need to load TabItems from plugins dynamically without the host application first knowing about the TabItem. In these cases you need to have the plugin register the View and ViewModel with the application domain.
This is very easy to do, and actually something I do for one of my MEF based projects. I have an post here, with some additional details as well.
All you need to do is add a Resource Dictionary to your plugin/extension and make sure that the host application loads it once the plugin has been imported.
To show you a fast example I would have a View.xaml in my extensions:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vw="clr-namespace:MyExtension.Test">
<DataTemplate DataType="{x:Type vw:TestViewModel}">
<vw:TestView/>
</DataTemplate>
</ResourceDictionary>
I then expose the ResourceDictinary using MEF to the Host like this:
private ResourceDictionary _viewDictionary = new ResourceDictionary();
public ResourceDictionary Dict
{
get
{
return _viewDictionary;
}
}
_viewDictionary.Source =
new Uri("/MyExtension.Test;component/View.xaml",
UriKind.RelativeOrAbsolute);
Last you use Application.Current.Resources.MergedDictionaries.Add to load the View.xaml into the host.
You Dont have to add controls you just have to specify the UserControl.
TabControl has two properties ItemTemplate && Content Template
ItemTemplate is for how the Tab will look where as
ContentTemplate is how the Tab Content will Look... so...
Xaml for the above
<TabControl Grid.Row="1"
ItemsSource="{Binding Path=TabList}"
SelectedItem="{Binding Path=SelectedTab,
Mode=TwoWay}"
<!--This is How tab will look--> >
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="20"
Height="20"
Margin="0,0,2,0"
Source="Images\TreeView\yourFavImg.png" />
<TextBlock Margin="0,4,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding Path=TabText}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<!--This will be the content for the tab control-->
<TabControl.ContentTemplate>
<DataTemplate>
<!--This User Control will contain the controls you like-->
<ViewLayer:YourFavUserControl />
</DataTemplate>
</TabControl.ContentTemplate>
you dont have to add controls if you use mvvm. you just have to create datatemplates for your viewmodel objects you wanna display.
all you need is a contentcontrol/presenter which is bind to your viewmodel and the datatemplate will show what you want.

Categories

Resources