I have created a BaseWindowView
and a BaseViewModel
in a self-defined framework which I'd like to use as a basis in all of my applications.
In the BaseViewModel
I have, for example, a method which allows me to add buttons. I can define a Command
, a ButtonImage
and a LabelString
. Here is the sample code for the call of this method:
AddButton(OpenAnyTabCommand, "../Images/image.png", "LabelString");
In my BaseWindowView
I have a RibbonMenue
where all of the RibbonButtons
that I have defined in the BaseViewModel
are shown:
<ItemsControl x:Name="CButtons" ItemsSource="{Binding Buttons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="ButtonStackPanel" Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ribbon:RibbonButton
x:Uid="Button"
LargeImageSource="{Binding Path=ImageString}"
Label="{Binding Path=LabelString}"
Command="{Binding Path=ButtonCommand}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have this in a sample project, and it works fine. Now I want to outsource the BaseWindowView
and the BaseViewModel
to a framework and use it from there.
My plan is: In each of my applications, I'd like to set the BaseWindowView
as the MainWindow
of my application. In this application itself I just want to have some UserControls
which should be shown as tabs in my BaseWindowView
. The buttons I've defined in the BaseViewModel
should call the defined Command
which opens a new tab and shows the ViewModel
behind this Command
.
So what is the best way to handle my problem? I know that there is no "classic inheritance" in XAML. Can I just do something like define the StartUpUri
in the App.xaml
to the framework view or is it "a little bit" trickier?
As an addition: I found that I can define the DataTemplate
for the TabItems
(which are UserControls
) in the App.xaml
like the following:
<DataTemplate DataType="{x:Type ViewModel:AnyViewModel}">
<view:TabItemAny/>
</DataTemplate>
@Sheridan: Here is the question about the BaseWindowView
.
Ok, so to start with, let's address using your
BaseWindowView
as theMainWindow
:First, in the
App.xaml
file, remove the declaration ofStartup
andStartupUri
properties from theApplication
definition. Then in theApp.xaml.cs
class, add a startup handler:This will open your
Window
instead of theMainWindow
.Now onto view inheritance... as you know, there is no such thing in WPF, but there (kind of) is a way around this problem. If, as you say, all of your views are
UserControl
based, then we can useContentControl
objects to display them, provided that relevantDataTemplate
objects exist.This basically means that if you want to use a particular
Window
as an outer template for your views, then you can if you add aContentControl
to display the view. As an example, I have an animatedWindow
that appears as a dialogue control with buttons which I bind several differentUserControl
s to, so that they all have the same overall appearance.In xaml:
And in the
Window
code behind:Using this class, I can either bind to this
ViewModel
property in xaml, or set it from a value passed in through a constructor. As all of my view models extend thisBaseViewModel
class, I can set this property to any of them.UPDATE >>>
The point of using the
ContentControl
and theDataTemplate
s to connect the views/view models is that we get away from 'hard coding'. I can use this setup in every application and I'm not tied to using any particular implementation.Now if you're saying that you actually want to use the same view/view model pairings in all of your different applications, then you should put your
DataTemplate
s to connect the views/view models in a separateResources
xaml file. That way, you can merge this file into yourApp.xaml
Resources
section in applications where you need to and not when you don't: