Unplug
Unplug

Reputation: 709

2 XAMLs using the same ViewModel class, but 2 separate instances

I have a big long xaml. I then created a UserControl for the menu part of the xaml to make it clean (I think). In my main xaml codebehind, I instantiated my ViewModel class and set it as the DataContext of the main xaml. In order to let main and menu xaml communicate to each other, I chose to use the same view model as the data context of the menu codebehind. I instantiated another ViewModel class. The my code works fine so far.

I 'feel' I am not doing this right, however. I believe I only need one instance of the ViewModel instance. But because the main.xaml.cs and the menu.xaml.cs don't know each other, I don't know how to share the instance.

Upvotes: 1

Views: 2083

Answers (3)

Kumareshan
Kumareshan

Reputation: 1341

You can put both of your usercontrol into the MainWindow.Xaml and set the data context in MainWindow.xaml.cs or expose a static property in your viewmodel of the viewmodeltype like this:

public class ViewModel
{
   private static ViewModel instance = new ViewModel();

   public static Viewmodel Instance
   {
       get
       {
          return instance;
       }
   }
} 

in your xaml.cs you can do the following:

DataContext = ViewModel.Instance;

You can repeat this line in any number of xaml.cs's, for all the XAML now you'll have only one instance.

Upvotes: 0

aybe
aybe

Reputation: 16672

You can add a property to your App.xaml.cs and then bind to it in your controls.

1st approach : as a XAML resource

Your model:

public class MyViewModel
{
    public int Hello { get; set; }    
}

App.xaml.cs:

<Application x:Class="WpfApplication12.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:wpfApplication12="clr-namespace:WpfApplication12"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <wpfApplication12:MyViewModel x:Key="MyViewModel" />
    </Application.Resources>
</Application>

Small note: there is no need to annotate the object with x:Shared="True" as it is the default value, the same instance will be returned. http://msdn.microsoft.com/en-us/library/aa970778.aspx

Your user control :

<UserControl x:Class="WpfApplication12.UserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid DataContext="{Binding Mode=OneWay, Source={StaticResource MyViewModel}}">
        <TextBlock Text="{Binding Path=Hello}" />
    </Grid>
</UserControl>

Now since your model is a resource, you can retrieve it by creating a property :

public MyViewModel MyViewModel
{
    get { return Application.Current.FindResource("MyViewModel") as MyViewModel; }
}

(you might want to store that reference in a field, however.)

2nd approach : as a conventional property

If for some reasons you prefer a conventional property, here's the syntax:

Note, the property is static and initialized in the static constructor.

public partial class App : Application
{
    static App()
    {
        MyViewModel = new MyViewModel();
    }

    public static MyViewModel MyViewModel { get; set; }
}

Binding to it in your user control:

<Grid DataContext="{Binding Source={x:Static wpfApplication12:App.MyViewModel}}"/>

Upvotes: 1

Suresh
Suresh

Reputation: 4149

You could have another view which wraps both your MenuView and MainView, and set the DataContext on the wrapper view, then both your MenuView and MainView will inherit and use the same DataContext.

Sample XAML for Wrapper View:

<UserControl x:Class="WpfApplication1.YourView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpfApplication1="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <wpfApplication1:YourMenuView Grid.Row="0"/>
        <wpfApplication1:YourMainView Grid.Row="1"/>
    </Grid>
</UserControl>

and Codebehind for WrapperView:

public partial class YourView : UserControl
{
    public YourView()
    {
        InitializeComponent();
        DataContext = new YourViewModel();
    }
}

Upvotes: 0

Related Questions