WPF: Set UserControl DataContext
Asked Answered
M

2

6

I have the following MainWindow that lays out a left side navigation panel and a right side display area (both of these are UserControls).

Can someone explain how to assign the DataContext of the navigation panel (LinksView.xaml) to that of LinksViewModel.cs. I would like to bind a Command (BtnCompanyClickCommand) to the button and define BtnCompanyClickCommand in LinksViewModel.cs.

I have tried various methods that I found on StackOVerflow to set the DataContext but none of these solutions seem to work (binding RelativeSource, naming view and binding to name, etc.).

MainWindow.xaml

<StackPanel Orientation="Horizontal">
    <vw:LinksView DataContext="{Binding RelativeSource={RelativeSource Self}}"/>
    <ContentControl Content="{Binding CurrentUserControl}" />

</StackPanel>

LinksView.xaml

<StackPanel Orientation="Vertical">
    <Button Content="Company" Width="75" Margin="3" Command="{Binding ElementName=Links,Path=BtnCompanyClickCommand}" />
</StackPanel>

FormsDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:vm="clr-namespace:SidekickAdmin.ViewModel"
                    xmlns:vw="clr-namespace:SidekickAdmin.View">

    <DataTemplate DataType="{x:Type vm:CompanySummaryViewModel}">
        <vw:CompanySummaryView>
            <ContentControl Content="{Binding }" />
        </vw:CompanySummaryView>
    </DataTemplate>

    <DataTemplate DataType="{x:Type vm:LinksViewModel}">
        <vw:LinksView />
    </DataTemplate>

</ResourceDictionary>

EDIT

So I finally came across this explanation of how to set the DataContext of a UserControl which has to be done on the first child item of the UserControl.

Here is the modified LinksView.xaml that works.

<StackPanel Orientation="Vertical">
    <StackPanel.DataContext>
        <vm:LinksViewModel />   <!-- Bind the items in StackPanel to LinksViewModel -->
    </StackPanel.DataContext>

    <Button Content="Company" Width="75" Margin="3" Command="{Binding BtnCompanyClickCommand}" />
</StackPanel>

However, I am still not clear on why I have to set the DataContext of the child element and not the UserControl and why the DataTemplate for LinksView (set in FormsDictionary.xaml) doesn't tie into the DataContext of LinksViewModel. Any explanation would be appreciated.

Malaspina answered 2/1, 2013 at 5:27 Comment(3)
Does it still work if you remove the DataContext piece that you added in your edit? I'll assume that you will have the MainWindow view's datacontext set in this scenario.Asteria
If I remove the <StackPanel.DataContext>... from my edit then LinksView has a DataContext of MainWindowViewModel.Malaspina
If there is no datacontext explicity set on the LinksView, WPF will walk up the tree looking for one - in your case the datacontext on MainWindow.Asteria
I
0

First you have to refer to your DataContext (LinksViewModel.cs) in your XAML code. You can do that either by directly instantiating it or use a ResourceDictionary. In the latter case you instantiate your DataConext either inside some .cs file or inside the ResourceDictionary .xaml file and store it in a named ResourceDictionary where you can find the reference later.

Second you simply have to associate the DataContext property of a View element like your LinksView.xaml with the corresponding DataContext.

This is pretty high-level and without any code but that's the basic idea behind it.

Ie answered 2/1, 2013 at 5:37 Comment(1)
Thanks, I understand I have to connect the DataContext to the XAML and like I said I have tried various solutions proposed on other questions on SO. However, I cannot get these to work with my application so I was hoping someone might be able to actually suggest some code that I could try. I did try setting the DataContext of the LinksView in the ResourceDictionary but that didn't work.Malaspina
P
0

there should be an instance of LinksViewModel in MainWindowViewModel:

MainWindowViewModel.cs:

class MainWindowViewModel
{
    public MainWindowViewModel()
    {
         LinksVM = new LinksViewModel();
    }

    public LinksViewModel LinksVM { get; private set; }
}

MainWindow.xaml

<StackPanel Orientation="Horizontal">
    <vw:LinksView DataContext="{Binding LinksVM}"/>
    <ContentControl Content="{Binding CurrentUserControl}" />
</StackPanel>

LinksView.xaml

<StackPanel Orientation="Vertical">
    <Button Content="Company" Width="75" Margin="3" Command="{Binding BtnCompanyClickCommand}" />
</StackPanel>

since LinksView is explicitly created in MainWindow, there is no need in DataTemplate - it can be removed

<DataTemplate DataType="{x:Type vm:LinksViewModel}">
    <vw:LinksView />
</DataTemplate>
Plumy answered 8/4, 2020 at 10:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.