Search code examples
c#wpfxamlbindingdatacontext

WPF DataContext in XAML, why and what's the correct approach


currently this is how i set my DataContext in MVVM, for my Windows and UserConrols

<UserControl.DataContext>
    <local:DataMainViewModel x:Name="vm"/>
</UserControl.DataContext>

However, i have been told never to do it this way, but i see alot of examples out there where many code is doing it. I did run into some weird issues before such as DataContext not having the same instance from my view, not sure.

Anyways, i just want to ask, what is the best way to do it? Can i keep this approach in XAML? I heard i should remove it and instead set in the view such as...

    public DataMainView()
    {
        InitializeComponent();
        DataContext = new DataMainViewModel();
    }

Which is the best and safest way to do it?

The reason i keep setting it in XAML is because I like the design approach XAML, makes the code cleaner, and best of all, i get the intellisense which comes to binding. If i should remove it in XAML, please share how i can get the intellisense of binding without setting DataContext in XAML. Because if i put it in code behind, i dont get the intellisense anymore and when i try to bind objects i have to type everything correctly from refering to my viewmodel.

Thanks, Tim


Solution

  • You should not explicitly set the DataContext of UserControls at all, neither in XAML nor in code behind.

    UserControls are supposed to inherit the value of their DataContext property from their parent element, and have their properties bound to properties of the object in the inherited DataContext.

    This typically looks like

    <Window ...>
        <Window.DataContext>
            <local:MainViewModel/>
        </Window.DataContext>
        ...
        <local:MyUserControl MyProperty="{Binding VmProperty}" .../>
    </Window>
    

    where VmProperty is a property of MainViewModel. If the main view model provides a sub view model with properties that are meant to be displayed by the UserControl, the Binding may look like

    <local:MyUserControl MyProperty="{Binding SubViewModel.SubVmProperty}" .../>
    

    Those Bindings won't work when the UserControl had explicity set its own DataContext.


    Alternatively, the elements in the XAML of the UserControl may also directly bind to the properties of the DataContext object, like

    <UserControl x:Class="MyNamespace.MyUserControl" ...>
        ...
        <TextBlock Text="{Binding SubVmProperty}"/>
        ...
    </UserControl>
    

    where you would instantiate the control like

    <local:MyUserControl DataContext="{Binding SubViewModel}"/>
    

    If the UserControl had set its own DataContext, the above Binding would fail as well.


    A UserControl is often instatiated by a DataTemplate like

    <DataTemplate DataType="{x:Type local:SubViewModel}">
        <local:MyUserControl/>
    </DataTemplate>
    

    where the DataContext is automatically assigned the object to which the DataTemplate is applied. This would also also fail to work if the UserControl had explicity set its own DataContext.