WPF: Cannot get View to change dynamically using DataTemplate - c#

I have a problem designing my WPF application. I cannot get the Views to change dynamically. The code to call another View is contained in the Views themselves. (I am trying to implement the MVVM pattern. I do not want any code behind in the View xaml files other than assigning the DataContext. An exception is made in the xaml file of the MainWindow).
Basically, I have a Window that contains a UserControl. The UserControl is my View and it is connected to another class serving as ViewModel through Datacontext.
What I want to do is to dynamically change this View/ViewModel pairs contained in the Window.
My idea was define a static property in the ViewModel of the MainWindow and store the ViewModel of the current View in it. Then I planned to use DataTemplates to automatically load a new View whenever a new ViewModel is stored in the static property.
I decided to use a static property because the code to load another ViewModel is contained in the ViewModels itself and I needed a central point with access from everywhere.
So far so good. My initial View loads and displays correctly.
However, pressing a button in that View to load the next View fails although the new ViewModel is correctly assigned to the static property.
I tried several things.
I defined DataTriggers within the ContentControl to react to changes in the static property. No help.
Implementing INotifyProperty and DependencyProperty failed in the end because of the static nature of the property (or I did something wrong).
I just can’t get it to work.
Do you have any ideas why this would be?
Do you have an idea how I could solve my general problem of dynamically displaying Views without using a static property in my MainWindow. I believe this is causing problems and I have a notion that I am not using the most elegant method. (I do want to maintain the concept of each View holding the code to load any other View)
This is a code fragment from the MainWindow:
<UserControl>
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:StartViewModel}">
<v:StartView></v:StartView>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:OverviewViewModel}">
<v:OverviewView></v:OverviewView>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentControl Content="{Binding ActiveViewModel}">/ContentControl>
</Grid>
</UserControl>
Code behind:
DataContext = new MainViewModel();
MainViewModel contains the definition for the property ActiveViewModel. The constructor for the class is static. All ViewModels inherit from BaseViewModel class:
private static BaseViewModel activeViewModel;
static public BaseViewModel ActiveViewModel
{
get { return activeViewModel; }
set { activeViewModel = value; }
}
Thanks a lot for your help.
Bye,
Eskender

Related

Custom XAML Binding SOURCE Class

I am trying to find a better way to declare the ViewModel a UWP XAML Page uses.
At this moment,
I declare a ViewModel class ViewModelClass that contains my data properties.
Then I declare an instance of that class as StaticResource of the Page. I like calling those VIEW for consistency across all my Page designs.
Finally, I declare the Page's DataContext as a Binding to the StaticResource VIEW.
This yields a page that understands what data structure is in use and allows AutoComplete when working Bindings. Nice, though lots of lines of same-old-same-old code.
Only, it is not really suitable to ViewModels as the declared resource is a static resource. It is instantiated when the page is instantiated. Most pages will receive a ViewModel parameter upon NavigatedTo, which cannot be used to replace the static resource, because it is, well. static.
So I end up changing the Page's DataContext upon navigation from the initial reference to VIEW to the ViewModel instance I actually want to use.
Big caveat is to declare the back-reference to the page's DataContext when deep in the bowels of a Master-Detail situation is rather horrible. Imagine a collection whose display is in part depending on a Master's property.
How do you tie back robustly to the DataContext of the page from anywhere inside the page?
I have tried giving the page a Name (PAGE for simplicity) and then using ElementName=PAGE, Path=DataContext.someProperty. Ugly, plus you lose all information of the class represented by DataContext.
Another approach is to create a Wrapper around the actual ViewModel called StaticViewModel that has only one property: public ViewModel viewModel. Now I can declare the wrapper as a StaticResource, and tell the page's top-level FrameworkElement to use VIEW.viewModel as its DataContext. Works, and reliably, but sooooo ackward and cumbersome.
I would LOVE to implement a SOURCE class for bindings called PageDataContext that would do nothing else but to loop into the page and get the DataContext from there.
Imagine: {Binding someProperty, Source={PageDataContext}
How would I go about declaring said Source class for a UWP app???
I would LOVE to implement a SOURCE class for bindings called PageDataContext that would do nothing else but to loop into the page and get the DataContext from there. Imagine: {Binding someProperty, Source={PageDataContext}
For your requriment, you could implement your viewmodel in the page Resources and give it x:key. When you bind the property of viewmodel you could access this viewmodel with x:key Source={StaticResource ViewModel} for more please refer the following code.
ViewModel
public class ViewModel
{
public ViewModel()
{
Visibility = false;
}
public bool Visibility { get; set; }
}
Xaml
<Page.Resources>
<local:ViewModel x:Key="ViewModel" />
</Page.Resources>
<TextBlock
Width="100"
Height="44"
Text="{x:Bind Name}"
Visibility="{Binding Visibility, Source={StaticResource ViewModel}}" />
Well, no dice so far.
Working with all those options I found that the best one is a Wrapper class that can be assigned to a static resource which in turn is the basis for the page's DataContext. The wrapped instance of the actual ViewModel is then assigned during OnNavigatedTo() and used as the DataContext of the basic FrameworkElement of the page.
Brr, so much verbose code.
STILL WONDERING how to implement a different version of a source directive. Is there no way to declare one's own Source for a Data Binding? Is this stuff really hard-coded into the framework???

ContentControl Content Property not changing with hosted content

I am trying to learn MVVM and have come across a weird snag. I have a main menu with a drawer control that comes out and shows a menu:
In the main window where this drawer is, I have a ContentControl where I set its content with a Binding.
<ContentControl x:Name="MainWindowContentControl" Content="{Binding Path=WindowContent}"/>
This window's binding is set to a view model.
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
and here is the ViewModel:
MainWindowViewModel.cs
public class MainWindowViewModel: ViewModelBase
{
private object _content;
public object WindowContent
{
get { return _content; }
set
{
_content = value;
RaisePropertyChanged(nameof(WindowContent));
}
}
public ICommand SetWindowContent { get; set; }
public MainWindowViewModel()
{
SetWindowContent = new ChangeWindowContentCommand(this);
}
}
So far up to this point, everything works fine. So for example, if I click "Recovery Operations", I get this:
RecoveryOperationsView.xaml
In "RecoveryOperationsView.xaml" (which is a UserControl) I also reference the view model from above like so..
<UserControl.DataContext>
<viewmodels:MainWindowViewModel/>
</UserControl.DataContext>
and have a button to call the command to change the Content property of the ContentControl from the main window..
<Button Grid.Row="2" Content="Restore Database" Width="150" Style="{StaticResource MaterialDesignFlatButton}" Command="{Binding SetWindowContent}" CommandParameter="DatabaseRecovery" >
In my class to process the commands, I change the content based off of the passed parameter using a switch statement like so
ChangeWindowContentCommand.cs
public class ChangeWindowContentCommand : ICommand
{
private MainWindowViewModel viewModel;
public ChangeWindowContentCommand(MainWindowViewModel vm)
{
this.viewModel = vm;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
switch (parameter)
{
case "Home":
viewModel.WindowContent = new HomeView();
break;
case "RecoveryOps":
viewModel.WindowContent = new RecoveryOperationsView();
break;
case "DatabaseRecovery":
viewModel.WindowContent = new DatabaseRestoreView();
break;
}
}
}
However, this is where I get lost... If I click something within this new window, say "Restore Database" and inspect it with a breakpoint, I can see the property being changed but the actual ContentControl Content property doesnt change to the new UserControl I made... I can change the content with anything in the drawer, but if I try to click a button in the hosted Content of the ContentControl nothing changes. What am I missing?
It's hard to be 100% sure without having your project to test with, but I am fairly confident that at least one of the issues is that your UserControl and your MainWindow use different instances of the MainWindowViewModel. You do not need to instantiate the VM for the user control, as it will inherit the DataContext from the MainWindow. The way it works in WPF is that if any given UIElement does not have theDataContext assigned explicitly, it will inherit it from the first element up the logical tree that does has one assigned.
So, just delete this code, and it should solve at least that issue.
<UserControl.DataContext>
<viewmodels:MainWindowViewModel/>
</UserControl.DataContext>
And since you're learning WPF, I feel obligated to provide a couple other tips. Even though you're using a ViewModel, you are still mixing UI and logic by creating a very specific implementation of ICommand and assigning a UI element through your ViewModel. This breaks the MVVM pattern. I know MVVM takes a little time to understand, but once you do, it is very easy to use and maintain.
To solve your problem, I would suggest creating View Models for each of your user controls. Please see this answer, where I go into quite a bit of detail on the implementation.
For switching the different views, you have a couple of options. You can either use a TabControl, or if you want to use a command, you can have a single ContentControl bound to a property of MainWindowViewModel that is of type ViewModelBase. Let's call it CurrentViewModel. Then when the command fires, you assign the view model of the desired user control to that bound property. You will also need to utilize implicit data templates. The basic idea is that you create a template for each of the user control VM types, which would just contains an instance of the Views. When you assign the user control VM to the CurrentViewModel property, the binding will find those data templates and render the user control. For example:
<Window.Resources>
<DataTemplate DataType = "{x:Type viewmodels:RecoveryOperationsViewModel}">
<views:RecoveryOperationsView/>
</DataTemplate>
<!-- Now add a template for each of the views-->
</Window.Resources>
<ContentControl x:Name="MainWindowContentControl" Content="{Binding CurrentViewModel}"/>
See how this approach keeps UI and logic at an arm's length?
And lastly, consider creating a very generic implementation of ICommand to use in all your ViewModels rather than many specific implementations. I think most WPF programmers have more or less this exact RelayCommand implementation in their arsenal.

How to bundle View, ViewModel and DataTemplate in a WPF application for easy reuse?

Situation:
I'd like to create a flexible application which is ViewModel driven.
The basic flow is like this:
Design the main ViewModel
Create a UserControl as View and a DataTemplate for the main ViewModel to select this View
If there are sub components, the are modelled by sub ViewModels
Create a UserControl as View and a DataTemplate for the sub ViewModel to select this View
If a sub view model needs to be presented, it is done via a DataTemplate.
This approach can also be seen here (option 8).
So the main window xaml looks something like this:
<Window>
<!-- somehow I need to add the mapping from ViewModel to View -->
<Grid>
<!-- the main ViewModel -->
<ContentPresenter Content="{Binding Path=Content}"/>
</Grid>
</Window>
The Content property might contain a view model that contains a list of elements named Children and it's associated DataTemplate might look like this:
The children are also flexibly rendered by a suitable DataTemplate.
<UserControl>
<Grid>
<StackPanel>
<!-- display the child ViewModels in a list -->
<ItemsControl ItemsSource="{Binding Path=Children}" />
</StackPanel>
</Grid>
</UserControl>
Question:
How should I organize the ViewModels, Views and their DataTemplates so I don't need to hardwire them in the MainWindow?
How do I then connect this to the main window?
It would be nice if it is stub-able, i.e. I can see the result during design time with a design time dataContext.
Basically I want to bundle the View, ViewModel and DataTemplate and be able to use them in an application that doesn't need to know about the details (e.g. some sub ViewModel implements a certain interface and is injected into the main ViewModel).
Have you looked into Prism.
The framework allows you to define regions within your UI that views can be registered against. I believe this answers your 2nd question (2).
xmlns:cal="http://www.codeplex.com/prism"
<Window>
<!-- somehow I need to add the mapping from ViewModel to View -->
<Grid>
<!-- the main ViewModel -->
<ContentPresenter cal:RegionManager.RegionName="MainRegion"/>
</Grid>
</Window>
For your first question (1) we structure our entities in the following way:
View - we have an abstract base class that looks similar too:
public abstract class ViewBase<T> : UserControl, IView<T> where T: IViewModel
{
public T ViewModel
{
get
{
return this.viewModel;
}
protected set
{
this.viewModel = value;
this.DataContext = this.viewModel;
}
}
public ViewBase(IUnityContainer container)
{
this.ViewModel = container.Resolve<T>();
}
}
This then allows us to create Views in xaml using the following:
<ui:ViewBase x:Class="MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:ui="NAMESPACE FOR VIEWBASE"
xmlns:vm="NAMESPACE FOR VIEWMODEL"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:TypeArguments="vm:MYVIEWMODEL">
In the code behind of a View we do the following:
public partial class MyView : ViewBase<IMyViewModel>
This then makes use of the constructor in the base class to resolve the ViewModel and set it to it's DataContext.
This then allows you to design your view (3) as you intended and also removes the need for having a DataTemplate.
Using the UnityContainer we then register the views as follows:
this.container.RegisterType<IMyView, MyView>();
this.container.RegisterType<IMyViewModel, MyViewModel>();
this.regionManager.RegisterViewWithRegion("MainRegion", typeof(IMyView));
Note that "MainRegion" here matches the RegionName specified in the MainWindow xaml. You can expand this further to use a TabControl if you wanted to display multiple views in the same area, or even break your MainWindow down into different regions.
I hope this helps.
1) You can in each view add DataTemplates in UserControl.Resources, i.e.
<UserControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:Customer1ViewModel}">
<views:Customer1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:Customer2ViewModel}">
<views:Customer2View/>
</DataTemplate>
</UserControl.Resources>
Now you defined for each ViewModel appropriate View.
You put only data templates for ViewModels that you expect in that View,
i.e. children's ViewModels
2) Hm, your MainWindow also has to have a ViewModel, i.e put in MainWindow DataContext an instance of MainWindows's ViewModel. That ViewModel has to contain the property Content (in which you put ViewModel for content).
You can do that manually in App.xaml.cs
public partial class App : Application
{
public App()
{
this.Startup += App_Startup;
}
public void App_Startup(object sender, StartupEventArgs e)
{
this.MainWindow = new MainWindow();
//create view model and set data context
MainWindowViewModel vm = new MainWindowViewModel();
this.MainWindow.DataContext = vm;
//show window
this.MainWindow.ShowDialog(vm);
}
}
3) I'm not sure about this, you probably will not be able to see results in design time.
I'm not sure if I'm fully understanding what exactly you want, if this doesn't help,
please replay to this answer with further explanation.

To use (DataContext) or not to use

I've got a dilemma regarding the DataContext. Let's inspect the following piece of XAML:
<Window xmlns:my="clr-namespace:MyNamespace.Controls"
... >
...
<my:MyControl Name="{Binding Prop1}" Value="{Binding Prop2}" />
</Window>
Obviously, the Window's code-behind contains something like:
DataContext = someViewModel;
Author's intentions are clear - he wants to bind MyControl's Name and Value to Window's DataContext's Prop1 and Prop2. And this will of course work. Unless. (dramatic pause)
Unless MyControl is a composite UserControl, which also wants to take advantage of short notation of bindings and sets its DataContext to its own viewmodel. Because then it will become clear, that the bindings in Window's XAML actually bind to MyControl's DataContext (previously inherited from Window's one) and now they will stop working (or worse, will keep working if MyControl's viewmodel actually contains properties named Prop1 and Prop21).
In this particular case solution is to bind in Window's code explicitly:
<Window x:Name="rootControl"
xmlns:my="clr-namespace:MyNamespace.Controls"
... >
...
<my:MyControl Name="{Binding ElementName=rootControl, Path=DataContext.Prop1}"
Value="{Binding ElementName=rootControl, Path=DataContext.Prop2}" />
</Window>
TL;DR If we're using short notation of bindings (when binding to DataContext) we may encounter quite tough to nail bugs resulting from bindings suddenly pointing to wrong DataContext.
My question is: how to use short binding notation without risk, that I'll bind to wrong DataContext? Of course I may use the short notation when I'm sure, that I'll be using inherited DataContext and long notation when I'm sure, that control will modify its DataContext. But that "I'm sure" will work only until first mistake, which will consume another hour of debugging.
Maybe I'm not following some MVVM rule? E.g. for example DataContext should be set only once on the top level and all composited controls should bind to something else?
1 I've gone through that, actually. The Window's DataContext contained a property named (say) Prop and the control replaced its DataContext with a class, which also contained a property Prop and everything worked fine. Problem appeared when I tried to use (unconsciously) the same pattern with non-matching property names.
By request:
Fragment of MyControl's code:
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(MyControl), new PropertyMetadata(null));
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int), typeof(MyControl), new PropertyMetadata(0));
Window's viewmodel:
public class WindowViewmodel : INotifyPropertyChanged
{
// (...)
public string Prop1
{
get
{
return prop1;
}
set
{
prop1 = value;
OnPropertyChanged("Prop1");
}
}
public int Prop2
{
get
{
return prop2;
}
set
{
prop2 = value;
OnPropertyChanged("Prop2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Now assume, that on changing of Name and Value dependency properties, MyControl generates some viewmodel and executes the code:
model = new MyControlViewModel(Name, Value);
this.DataContext = model;
And internal MyControl controls bind to this DataContext.
From now on, the original Name and Value bindings will no longer work.
Unless MyControl is a composite UserControl, which also wants to take advantage of short notation of bindings and sets its DataContext to its own viewmodel.
And that's where I stopped reading. This is, imho, a MVVM anti-pattern.
The reason for this is twofold. First, you screw with anybody who is using the control. "Hey," you say, "you can't bind your stinky VM to my beautiful UI. You have to use MY custom VM!" But what if your VM is hard to use, lacks logic or features needed by the overall application? What happens when, to use your UI, we have to translate our VM/models back and forth with your VM? Pain in the butt.
Second is that your custom control is UI. Its logic is UI logic, and so it is unnecessary to use a view model. It is better to expose DependencyProperties on your control and update your UI as necessary. That way anybody can bind to your UI and use it with any model or view model.
You can solve your problems by simply not using what you call a 'composite control. While I understand that you want to encapsulate some functionality in the associated view model, you don't need to set the view model to the UserControl.DataContext internally.
What I mean by this is that you can have a view model for any or all of your UserControls, but they're data classes, not UI classes, so keep them out of the view code. If you use this method of adding DataTemplates into Resources, then you won't need to set any DataContext properties at all:
<DataTemplate DataType="{x:Type ViewModels:YourUserControlViewModel}">
<Views:YourUserControl />
</DataTemplate>
The final difference is that you should add your view model for your UserControls as properties in a parent view model. This way, you still have no duplicated code (except maybe just a property declaration) and more importantly, you have no Binding problems from mixing DataContext values.
UPDATE >>>
When using this DataTemplate method of hooking up views and view models, you can display your view by Binding your view model property to the Content property of a ContentControl like this:
<ContentControl Content="{Binding YourViewModelProperty}" />
At run time, this ContentControl will be rendered as whatever view or UserControl that you defined in the DataTemplate of the relevant type for that property. Note that you shouldn't set the x:Key of the DataTemplate, otherwise you'd also need to set the ContentControl.ContentTemplate property and that can limit the possibilities afforded by this method.
For example, without setting the x:Key property on your DataTemplates, you could have a property of a base type and by setting it to different sub class, you can have different views for each from the one ContentControl. That is the basis of all of my views... I have one property of a base class view model data bound like this example and to change views, I just change the property to a new view model that is derived from the base class.
UPDATE 2 >>>
Here's the thing... you shouldn't have any 'proxy' object in your UserControls doing anything... it should all be done through properties. So just declare a DependencyProperty of the type of that object and supply it from the view model through data Binding. Doing it this way means that it will be easy to test the functionality of that class, whereas testing code behind views is not.
And finally, yes, it's perfectly fine doing this in MVVM:
<Controls:SomeUserControl DataContext="{Binding SomeViewModelProperty}" />
The overriding goal of MVVM is just to provide separation between the UI code and the view model code, so that we can easily test what's in the view models. That is why we try to remove as much functionality code from the views as possible.
within a usercontrol you should never set the datacontext to "this" or a new viewmodel. a developer/user of your MyUsercontrol expect that the datacontext inherit from top to bottom (from mainwindow to your myusercontrol).
your usercontrol xaml should use element binding
MyUserControl.xaml
<UserControl x:Name="uc">
<TextBlock Text="{Binding ElementName=uc, Path=Name}"/>
<TextBlock Text="{Binding ElementName=uc, Path=Value}"/>
this means your following code will work now in every situation
<Window xmlns:my="clr-namespace:MyNamespace.Controls">
<my:MyControl Name="{Binding Prop1}" Value="{Binding Prop2}" />
</Window>
the property Prop1 from Datacontext mainwindow is bound to the DP Name from your MyUsercontrol and the Textblock.Text within your MyUsercontrol is bound to the DP Name.
I've never met such a problem. It seems to be a little bit theoretical to me but maybe because of my approach to working with DataContext in WPF.
I minimize the explicit use DataContext property. I set it manually only for windows.
I have one dedicated method which is responsible for displaying new windows and it is the only one place where the DataContext property is set explicitly.
DataContext property for Windows is set to root ViewModel which contains child ViewModels, which contain...
I allow WPF to select which View should be used to display given a ViewModel by using DataTemplate
In my application I have a single ResourceDictionary which contains mappings between all ViewModels and Views.

Binding a ContentControl to UserControl, and reuse same instance

I'm trying to bind a ContentControl's Content to a UserControl I have instantiated in my ViewModel. I cannot use the method with binding to a ViewModel and then have the UserControl be the DataTemplate of the ViewModel, as I need the Content of the ContentControl to be able to change frequently, using the same instance of the UserControls/Views, and not instantiate the views each time i re-bind.
However, when setting the UserControl-property to a UserControl-instance, and then when the view is rendered/data-bound I get: Must disconnect specified child from current parent Visual before attaching to new parent Visual. Even though I have not previously added this UserControl to anywhere, I just created this instance earlier and kept it in memory.
Are there a better way to achieve what I am doing?
In the ViewModel
public class MyViewModel : INotifyPropertyChanged
{
//...
private void LoadApps()
{
var instances = new List<UserControl>
{
new Instance1View(),
new Instance2View(),
new Instance3View(),
};
SwitchInstances(instances);
}
private void SwitchInstances(List<UserControl> instances)
{
CenterApp = instances[0];
}
//...
private UserControl _centerApp;
public UserControl CenterApp
{
get { return _centerApp; }
set
{
if (_centerApp == value)
{
return;
}
_centerApp = value;
OnPropertyChanged("CenterApp");
}
}
//...
}
In the View.xaml
<ContentControl Content="{Binding CenterApp}"></ContentControl>
Too long for a comment.
Building up on what #Kent stated in your comment, The whole point of MVVM is to disconnect the view-model from view related stuff(controls) which blocks the testing capability of GUI applications. Thus you having a UserControl / Button / whatever graphical view-related item negates the entire principle of MVVM.
You should if using MVVM comply with its standards and then re-address your problem.
With MVVM you normally have 1 view <-> 1 view-model
View knows about its View Model(Normally through DataContext). Reverse should not be coded into.
You try to put logic controlling the view in the view-model to allow testing logic(Commands and INPC properties)
... and quite a few more. It's pretty specific in the extents of view-model not having view related stuff for eg not even having properties in view-model like Visibility. You normally hold a bool and then in the view use a converter to switch it to the Visibility object.
Reading up a bit more into MVVM would certainly help you,
Now for something to address your current issue:
Following a MVVM structure,
your going to have ViewModels such as
Main: MyViewModel
Derive all instance ViewModels from a base to allow them being kept in a list.
List or hold individually Instance1ViewModel, Instance2ViewModel, Instance3ViewModel in MyViewModel (Either create it yourself or if your using an IOC container let it inject it)
Have MyViewModel expose a property just like your posted example:
Example:
// ViewModelBase is the base class for all instance View Models
private ViewModelBase _currentFrame;
public ViewModelBase CurrentFrame {
get {
return _currentFrame;
}
private set {
if (value == _currentFrame)
return;
_currentFrame = value;
OnPropertyChanged(() => CurrentFrame);
}
}
Now in your MyView.xaml View file you should(does'nt have to be top level) set the top-level DataContext to your MyViewModel
Your View's xaml can then be declared like:
Example:
...
<Window.Resources>
<DataTemplate DataType="{x:Type local:Instance1ViewModel}">
<local:Instance1View />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Instance2ViewModel}">
<local:Instance2View />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Instance3ViewModel}">
<local:Instance3View />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding Path=CurrentFrame}" />
</Grid>
...
Thats it!. Now you just switch the CurrentFrame property in your view-model and make it point to any of three instance view-models and the view will be correspondingly updated.
This gets you an MVVM compliant application, for your other issue of working around not having to recreate views dynamically based on DataTemplate you could follow the approaches suggested here and expand it for your own usage.

Categories

Resources