0
votes

I'm structuring my WPF application using MVVM Light and am creating the ViewModel using the IOC.

The page initializes its DataContext like this:

DataContext="{Binding Main, Source={StaticResource Locator}}"

A TabControl has its content bound to another ViewModel, so binding from within the TabControl will access the tab ViewModel by default.

Now, how can I instead access the page ViewModel in XAML?

Before switching to use IOC, the ViewModel was created as a StaticResource and I could access it like this

Zoom="{Binding Zoom, Source={StaticResource ViewModel}, Mode=TwoWay}"

Then I could also access it via the Locator, however I don't like this syntax as what happens if this ViewModel instance was created with a key? I don't think the content binding should care about such details.

Zoom="{Binding Main.Zoom, Source={StaticResource Locator}, Mode=TwoWay}"

What's the right way of doing it?

1

1 Answers

1
votes

You can use RelativeSource Binding with Mode set to FindAncestor. This will allow you to bind to the DataContext of your window (or any other element that contains your tab control) without knowing anything about it.

I set up a simple example based on your description. I have 2 simple View Models:

public class MainViewModel : ViewModelBase
{
    public double Zoom { get; } = 1;
}

public class TabViewModel : ViewModelBase
{
    public double Zoom { get; } = 2;
}

And here is the content of my xaml:

<Window
...blah blah blah...
DataContext="{Binding Main, Source={StaticResource Locator}}"
>
<Grid>
    <TabControl>
        <TabItem DataContext="{Binding Tab, Source={StaticResource Locator}}" Header="TabItem">
            <StackPanel>
                <Label Content="{Binding DataContext.Zoom, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" />
                <Label Content="{Binding Zoom}" />
            </StackPanel>
        </TabItem>
    </TabControl>
</Grid>

The first label gets it's value from the MainViewModel, and the second - from the TabViewModel.

The one downside I found is design time data for such a binding does not work properly. This can be solved by providing a fallback value.

Hope this solves your problem.