Answered How can I save a reference of dataContext and bind the reference with multiple user controls in wpf?

destro

Well-known member
Joined
Mar 28, 2020
Messages
46
Programming Experience
1-3
I have a mainViewModel and a mainwindow with 4 user controls in it binded to their respective view models.

The MainViewModel does some calculation based on inputViewModel.cs and InputView User Control and shows the result in resultView.

I want to use the data context of calculated result in MainViewModel. So far I have used the mainWindow.xaml.cs class to set the same dataContext of new window which is done as follows:

C#:
namespace SweWPF
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModels.MainViewModel();         
        }
        public ViewModels.MainViewModel ViewModel { get { return (ViewModels.MainViewModel)DataContext; } }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ResultWindow resultWindow = new ResultWindow();
            resultWindow.DataContext = this.DataContext;
            resultWindow.Show();
        }

    }


This is the xaml code of MainWindow:
C#:
<Window x:Class="SweWPF.MainWindow"
        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"
        xmlns:vm="clr-namespace:SweWPF.ViewModels"
        xmlns:vw="clr-namespace:SweWPF.Views"
        d:DataContext="{d:DesignInstance Type=vm:MainViewModel, IsDesignTimeCreatable=True}"
        Title="Manglam Stellaris"
        WindowState="Maximized"
        Height="384" Width="733">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="280" />
            <ColumnDefinition Width="4*" />
        </Grid.ColumnDefinitions>

        <vw:ConfigView Grid.Row="0" Grid.ColumnSpan="2" DataContext="{Binding Config}" />

        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" Grid.RowSpan="2"/>
            <vw:InputView DataContext="{Binding Input}" Grid.RowSpan="2" />
            <Button Grid.Row="1" Content="Calculation" Padding="16,8" Margin="0,244,21,0" Command="{Binding DoCalculationCommand, Mode=OneWay}" Click="Button_Click" />
        </Grid>

        <vw:ResultView Grid.Row="1" Grid.Column="1" DataContext="{Binding Result}"/>
    </Grid>
</Window>

This is the ResultView UserControl xaml code:

C#:
<UserControl x:Class="SweWPF.Views.ResultView"
             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:vm="clr-namespace:SweWPF.ViewModels"
             mc:Ignorable="d"
             d:DataContext="{d:DesignInstance Type=vm:CalculationResultViewModel, IsDesignTimeCreatable=True}"
             d:DesignHeight="360" d:DesignWidth="629">
    <Grid>
        <ScrollViewer Padding="4">
            <StackPanel>
                <!-- Date and calculations -->
                <Label Style="{StaticResource SectionLabel}">Date and calculation</Label>
                <Grid Grid.Column="0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Row="0" Grid.Column="0" Content="Date UTC" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="1" Grid.Column="0" Content="{Binding DateUTC}" />

                    <Label Grid.Row="0" Grid.Column="1" Content="Julian Day" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="1" Grid.Column="1" Content="{Binding JulianDay}" />

                    <Label Grid.Row="0" Grid.Column="2" Content="Delta T" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="1" Grid.Column="2" Content="{Binding DeltaTSec}" />

                    <Label Grid.Row="2" Grid.Column="0" Content="Ephemeris Time" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="3" Grid.Column="0" Content="{Binding EphemerisTime}" />

                    <Label Grid.Row="2" Grid.Column="1" Content="Sideral Time" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="3" Grid.Column="1" Content="{Binding SideralTime, ConverterParameter=hour, Converter={StaticResource DoubleToTimeFormatConverter}}" />

                    <Label Grid.Row="4" Grid.Column="0" Content="Mean Ecliptic Obliquity" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="5" Grid.Column="0" Content="{Binding MeanEclipticObliquity, Converter={StaticResource DoubleToDegreesFormatConverter}}" />

                    <Label Grid.Row="6" Grid.Column="0" Content="True Ecliptic Obliquity" Style="{StaticResource CaptionLabel}"/>
                    <Label Grid.Row="7" Grid.Column="0" Content="{Binding TrueEclipticObliquity, Converter={StaticResource DoubleToDegreesFormatConverter}}" />

                    <Label Grid.Row="4" Grid.Column="1" Content="Nutation in Longitude" Style="{StaticResource CaptionLabel}" />
                    <Label Grid.Row="5" Grid.Column="1" Content="{Binding NutationLongitude, Converter={StaticResource DoubleToDegreesFormatConverter}}" />

                    <Label Grid.Row="6" Grid.Column="1" Content="Nutation Obliquity" Style="{StaticResource CaptionLabel}" />
                    <Label Grid.Row="7" Grid.Column="1" Content="{Binding NutationObliquity, Converter={StaticResource DoubleToDegreesFormatConverter}}" />

                    <Label Grid.Row="4" Grid.Column="2" Content="ARMC" Style="{StaticResource CaptionLabel}" />
                    <Label Grid.Row="5" Grid.Column="2" Content="{Binding ARMC, Converter={StaticResource DoubleToDegreesFormatConverter}}" />
                </StackPanel>
        </ScrollViewer>
    </Grid>
</UserControl>


My New window opens up when I click on calculate button and shows the same ResultView user control as on MainWindow but I want to create custom user controls which will be placed in another window called ResultWindow and user controls can be switched using the drop down combo.

All the user control have to inherit from the same data context as of mainWindow. Can someone point me in right direction on what steps to take to share dataContext between usercontrols by creating individual references of the datacontext?
 
There is no restriction that says there is 1-to-1 relationship of type of view model to a view. You could have multiple types of windows share a common type of view model, or you could have a single window support different kinds of view models.

Additionally, you can also have multiple windows share the same instance of a view model. For example you could have one user control that shows a pie chart, and another user control display a heat map, and yet another user control display a data grid, but have all three of them sharing the same instance of a particular view model.
 
There is no restriction that says there is 1-to-1 relationship of type of view model to a view. You could have multiple types of windows share a common type of view model, or you could have a single window support different kinds of view models.

Additionally, you can also have multiple windows share the same instance of a view model. For example you could have one user control that shows a pie chart, and another user control display a heat map, and yet another user control display a data grid, but have all three of them sharing the same instance of a particular view model.
So how do I create an instance along with data context in a way that all my user controls can use it?
 
So how do I create an instance along with data context in a way that all my user controls can use it?
can you give me an example using mainViewModel mentioned above for binding it's data context with a new user control?
 
You are already doing it with your lines 16-17 above in your OP. You are creating an instance and setting the DataContext. Basically, you are doing property injection. You could make the constructor of the user control take a view model as a parameter and do constructor injection.
 
You are already doing it with your lines 16-17 above in your OP. You are creating an instance and setting the DataContext. Basically, you are doing property injection. You could make the constructor of the user control take a view model as a parameter and do constructor injection.
That sounds good I'll go ahead give it a try.

For every new user control do I build a new view model?? I hope that is the only case as there will be multiple user control using same dataContext but different values stored in observable collection. Can you confirm?
 
Alternatively, if you want to do thing in declarative manner in the XAML, instead of programmatically in the code behind, see how the binding is done in the link below:
 
Back
Top Bottom