How to declare multiple viewmodels as static resource in a datacontext of a Grid in WPF?

MERUN KUMAR MAITY 636 Reputation points
2022-05-17T23:53:12.787+00:00

I have a WPF application where I use multiple view models. Sometimes I use the same view model multiple times, though I have some other different type of view models. My main question is, how can I declare multiple view models as a single data context in one Grid.

Here is the code of one of my view model :

using System.ComponentModel;
     using System.Windows;
     namespace TabControlBindSlide
     {
       public partial class MainWindow : Window
       {
         public MainWindow()
         {
           InitializeComponent();
         }
       }
       class TestViewModel : INotifyPropertyChanged
       {
         private int _selected;
         public int Selected
         {
           get { return _selected; }
           set
           {
             int temp = _selected;
             _selected = value;
             _previousSelected = temp;
             NotifyPropertyChanged("Selected", temp, value);
             NotifyPropertyChanged("PreviousSelected", temp, temp);
           }
         }
         int _previousSelected = 0;
         public int PreviousSelected
         {
           get { return _previousSelected; }
         }
         public event PropertyChangedEventHandler PropertyChanged;
         protected void NotifyPropertyChanged<T>(string propertyName, T oldvalue, T newvalue)
         {
           OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(propertyName, oldvalue, newvalue));
         }
         public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
         {
           PropertyChangedEventHandler handler = PropertyChanged;
           if (handler != null)
             handler(sender, e);
         }
       }
       public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs
       {
         public virtual T OldValue { get; private set; }
         public virtual T NewValue { get; private set; }

     public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue)
         : base(propertyName)
     {
       OldValue = oldValue;
       NewValue = newValue;
     }
   }
 }

And I use this in my Grid as a static resource of a data context.

Here is my MainWindow.xaml code :

 <Grid  DataContext="{StaticResource vm}" >
         <Grid.RowDefinitions>
             <RowDefinition Height="*"/>
             <RowDefinition Height="50"/>
         </Grid.RowDefinitions>
         <TabControl     SelectedIndex="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"     Grid.Row="0"   x:Name="TestTabs">
             <TabItem Name="Tab1" Header="News" />
             <TabItem Name="Tab2" Header="DLC" />
             <TabItem Name="Tab3" Header="Settings"/>
         </TabControl>
         <DockPanel  x:Name="rp" Grid.Row="0" LastChildFill="False" HorizontalAlignment="Stretch">
             <Canvas DockPanel.Dock="Left" >
                 <Rectangle x:Name="Rect1" Fill="#ff0000" VerticalAlignment="Top"  Height="4" Margin="0,25,0,0" 
                            SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.EdgeMode="Aliased" 
                            Width="{Binding ElementName=TestTabs, Path=SelectedItem.ActualWidth}"  RenderOptions.BitmapScalingMode="HighQuality" />
             </Canvas>
         </DockPanel>
         <StackPanel Orientation="Horizontal" Grid.Row="1">
             <Label Content="selected" Width="100" Height="40" />
             <TextBox x:Name="sele" Text="{Binding Selected}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
             <Label Content="previousSelected"  Width="100" Height="40"/>
             <TextBox x:Name="prev" Text="{Binding PreviousSelected,Mode=OneWay}" Width="100" Height="40" Background="AliceBlue" Margin="5"/>
         </StackPanel>
     </Grid>

If you look the code carefully, then you see that the Grid has only one data context as static resource which is a view model name VM. This line <Grid DataContext="{StaticResource vm}" >. How I declare more view models in that Grid because this is my main Grid, and as the application became more mature the more features will be added into it, thus the application will get more complexity. Complex application have lot of view models involved.

I also try to declare the view model as a static resource in the data context of a Dock panel but it does not working. I still don't know that how the view model so tied up with the Grid?

Developer technologies Windows Presentation Foundation
Developer technologies C#
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2022-05-19T03:08:48.557+00:00

    You could bind different DataContexts to different controls.

    A control cannot be bound to multiple different DataContexts. ( A control can only have one object set to its DataContext property.) For more information, you could refer here.

    However, the binding does not have to be bound to its DataContext. You can use other binding properties to specify a different source for the binding. Common properties for changing binding sources are Source, RelativeSource, and ElementName. You can refer here for more details.

    • You can only change the binding source for a specific binding, like you did in the Command binding.
    • Alternatively, you can change it for the entire control by setting or binding the control's DataContext property to something else.

    MainWindow.xaml:

         <Window.Resources>  
                <local:MainViewModel x:Key="mvm"/>  
            </Window.Resources>  
            <Grid DataContext="{StaticResource mvm}" >  
                <Grid.RowDefinitions>  
                    <RowDefinition/>  
                    <RowDefinition/>  
                </Grid.RowDefinitions>  
                <Grid  x:Name="grid1" Background="AliceBlue" Height="100" DataContext="{Binding VM1}" >  
                    <TextBlock VerticalAlignment="Top" Foreground="Black" Background="White" HorizontalAlignment="Left" Text="{Binding String1}" Width="100" Height="40">  
                        <TextBlock.ToolTip>  
                            <!--<TextBlock  Background="White" Foreground="Black"  Width="100" Height="40" Text="{Binding ElementName=tb,Path= Text}"/>-->  
                            <TextBlock>  
                                <Run Text="{Binding Source={x:Reference tb}, Path=Text}" FontWeight="Bold"/>  
                            </TextBlock>  
                        </TextBlock.ToolTip>  
                    </TextBlock>  
                    <TextBlock  Background="White" Foreground="Black"  Width="100" Height="40" Text="{Binding ElementName=tb,Path=DataContext.String2}"/>  
                </Grid>  
                <Grid x:Name="grid2"  Grid.Row="1" Background="LightGreen"  Height="100" DataContext="{Binding VM2}">  
                    <TextBlock x:Name="tb" VerticalAlignment="Top" Foreground="Black"  Background="White" HorizontalAlignment="Left" Text="{Binding String2}" Width="100" Height="40"/>  
                </Grid>  
            </Grid>  
    

    MainWindow.xaml.cs:

     public partial class MainWindow : Window  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
        }  
      }  
      public class MainViewModel  
      {  
        public ViewModel1 VM1{ get; set; }  
        public ViewModel2 VM2 { get; set; }  
        public MainViewModel()  
        {  
          VM1=new ViewModel1();  
          VM2=new ViewModel2();  
        }  
      }  
      public class ViewModel1   
      {  
        public string String1 { get;set;} ="string1";  
      }  
      public class ViewModel2   
      {  
        public string String2 { get;set;}="string2";  
      }  
    

    The result:
    203536-image.png


    If the response is helpful, please click "Accept Answer" and upvote it.
     Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread. 

    [5]: https://learn.microsoft.com/en-us/answers/articles/67444/email-notifications.html


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.