简体   繁体   English

MVVM从TabControl绑定到Page.DataContext

[英]MVVM Bind to Page.DataContext from TabControl

I'm structuring my WPF application using MVVM Light and am creating the ViewModel using the IOC. 我正在使用MVVM Light构建WPF应用程序,并正在使用IOC创建ViewModel。

The page initializes its DataContext like this: 该页面将如下初始化其DataContext:

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. TabControl的内容绑定到另一个ViewModel,因此默认情况下,从TabControl内部进行绑定将访问选项卡ViewModel。

Now, how can I instead access the page ViewModel in XAML? 现在,我该如何在XAML中访问ViewModel页面?

Before switching to use IOC, the ViewModel was created as a StaticResource and I could access it like this 在切换为使用IOC之前,ViewModel已创建为StaticResource,我可以像这样访问它

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? 然后,我也可以通过Locator访问它,但是我不喜欢这种语法,如果使用键创建此ViewModel实例会发生什么呢? 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? 正确的做法是什么?

You can use RelativeSource Binding with Mode set to FindAncestor. 您可以将RelativeSource Binding的Mode设置为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. 这将使您可以绑定到窗口的DataContext(或包含选项卡控件的任何其他元素)而无需了解任何信息。

I set up a simple example based on your description. 我根据您的描述建立了一个简单的示例。 I have 2 simple View Models: 我有2个简单的视图模型:

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: 这是我的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. 第一个标签从MainViewModel获取其值,第二个标签从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. 希望这能解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM