Reputation: 709
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
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
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
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