BrianKE
BrianKE

Reputation: 4185

WPF: Set UserControl DataContext

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.

Upvotes: 6

Views: 4283

Answers (2)

ASh
ASh

Reputation: 35646

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>

Upvotes: 0

marc wellman
marc wellman

Reputation: 5886

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.

Upvotes: 0

Related Questions