C# 在WPF MVVM应用程序中的选项卡之间正确导航

C# 在WPF MVVM应用程序中的选项卡之间正确导航,c#,wpf,xaml,mvvm,tabs,C#,Wpf,Xaml,Mvvm,Tabs,我正在使用m-V-VM模式(如果相关的话,我正在使用galasoft)执行WPF应用程序,但在tabcontrol中导航时遇到问题。 我正在跑步时添加标签。所有的绑定似乎都进行得很顺利:在选项卡内部或选项卡的标题中。 我已将tabcontrol绑定到可观察列表。通过一个界面,我将几种类型的viewmodel添加到此列表中,绑定似乎是正确的。 我的XAML代码如下所示: <Grid> <Grid.Resources> <DataTemplate

我正在使用m-V-VM模式(如果相关的话,我正在使用galasoft)执行WPF应用程序,但在tabcontrol中导航时遇到问题。
我正在跑步时添加标签。所有的绑定似乎都进行得很顺利:在选项卡内部或选项卡的标题中。 我已将tabcontrol绑定到可观察列表。通过一个界面,我将几种类型的viewmodel添加到此列表中,绑定似乎是正确的。
我的XAML代码如下所示:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="itemTemplate">
            <TechnicalControls:ItemTab />
        </DataTemplate>
    </Grid.Resources>

    <TabControl Grid.Row="1" x:Name="MainTab" Grid.Column="1" 
            ItemsSource="{Binding TabViewModels}"
            SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"

            ItemContainerStyleSelector="{StaticResource LastItemStyleSelector}"
            ItemTemplate="{StaticResource itemTemplate}"
            >

        <TabControl.Resources>
            <DataTemplate DataType="{x:Type VM:JobViewModel}" x:Shared="False" >
                <FunctionnalControls:Job />
            </DataTemplate>
            <DataTemplate DataType="{x:Type VM:ExcelJobViewModel}" x:Shared="False">
                <FunctionnalControls:ExcelJob />
            </DataTemplate>
            <DataTemplate DataType="{x:Type VM:MonitoringViewModel}" x:Shared="False">
                <FunctionnalControls:Monitoring />
            </DataTemplate>
            <DataTemplate DataType="{x:Type VM:ErrorViewModel}" x:Shared="False">
                <FunctionnalControls:Error />
            </DataTemplate>                

        </TabControl.Resources>
    </TabControl>
</Grid>

例如,如果我从一个ExcelJob转到另一个ExcelJob usercontrol,则新的usercontrol无法正确加载,但它会发生变化,然后它就会工作。例如,如果我只进行监视,我就可以从一个ExcelJob转到另一个ExcelJob

我已经看过了,但对我来说不起作用。
我也看过:它说我们不应该使用输入,因为你可以集中它们。我已尝试将users控件上的IsEnabled属性设置为false。我是在标签改变的时候做的。它不起作用

我能看到的唯一解决方案是通过另一个新的usercontrol,在每次更改选项卡时都不使用其他用途,但这很难看,我很确定,微软考虑过这一点,并提出了一个更好的解决方案

如有必要,我可以把代码的视图模型

编辑:只是澄清一下,当我单击具有相同控件的其他选项卡时,它显示的不是新的usercontrol,而是上一个。为了查看新的选项卡,我必须切换到另一个带有另一个usercontrol的选项卡,然后返回到我想要查看的选项卡。
我已经查看了debug,当我单击另一个选项卡时,它不会调用viewmodel

<UserControl x:Class="App.ExcelJob"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             DataContext="{Binding Main.ExcelJobVM, Source={StaticResource Locator }}">
    <Grid >
        <Label>Futur Excel Job</Label>
        <TextBox Width="200" Height="60" Text="{Binding Header}"/>
    </Grid>
</UserControl>

未来的卓越工作
因此Main返回Mainviewmodel,Main.ExcelJobVM返回usercontrol的良好viewmodel。返回的isntance基于所选索引。

我唯一需要的是通过加载好的viewmodel,强制重新绘制usercontrol或调用方法来更新datacontext。我试过了,到目前为止我失败了。我不确定我在做什么,因为我想使用tabcontrol的event SelectionChanged,但它会在代码背后,我不知道它是否仍然尊重MVVM模式。

问题是您的
用户控件中有
DataContext
硬编码,您的
UserControl
是一个模板

当您切换到使用相同
模板的选项卡时,WPF不需要重新绘制模板,只需更改模板后面的
DataContext
。但是在您的例子中,
UserControl
中有
DataContext
硬编码,因此它不使用TabItem中的现有数据上下文

最好的解决方案是从用户控件中删除
DataContext
绑定,并在所选项目更改时从
TabItem
继承该绑定

例如:

WPF说

用户已选择显示
ExcelJobA
。由于DataTemplate,让我使用ExcelJob用户控件绘制它

因此,实际显示的
ExcelJob
UserControl不会被重新创建或重新绘制,只会更改其后面的
DataContext

但是,因为您在
用户控件
中硬编码了
数据上下文
,所以从所选项目获得的实际数据上下文永远不会被使用,因为从
内部指定的
DataContext
始终优先于从视觉树的更上层继承的
DataContext

您需要从
UserControl
内部删除
DataContext
绑定,并让它从TabControl的
SelectedItem
正常传递,这样就可以正常工作了

<TabItem>
    <ContentPresenter DataContext="ExcelJobA">
        <local:ExcelJob /> <!-- DataContext inherited from the ContentPresenter -->
    </ContentPresenter> 
</TabItem>

问题是在
UserControl
中硬编码了
DataContext
,而
UserControl
是一个模板

当您切换到使用相同
模板的选项卡时,WPF不需要重新绘制模板,只需更改模板后面的
DataContext
。但是在您的例子中,
UserControl
中有
DataContext
硬编码,因此它不使用TabItem中的现有数据上下文

最好的解决方案是从用户控件中删除
DataContext
绑定,并在所选项目更改时从
TabItem
继承该绑定

例如:

WPF说

用户已选择显示
ExcelJobA
。由于DataTemplate,让我使用ExcelJob用户控件绘制它

因此,实际显示的
ExcelJob
UserControl不会被重新创建或重新绘制,只会更改其后面的
DataContext

但是,因为您在
用户控件
中硬编码了
数据上下文
,所以从所选项目获得的实际数据上下文永远不会被使用,因为从
内部指定的
DataContext
始终优先于从视觉树的更上层继承的
DataContext

您需要从
UserControl
内部删除
DataContext
绑定,并让它从TabControl的
SelectedItem
正常传递,这样就可以正常工作了

<TabItem>
    <ContentPresenter DataContext="ExcelJobA">
        <local:ExcelJob /> <!-- DataContext inherited from the ContentPresenter -->
    </ContentPresenter> 
</TabItem>


我注意到的第一件事是您同时拥有
SelectedItem
SelectedInd
<TabItem>
    <ContentPresenter DataContext="ExcelJobA">
        <local:ExcelJob /> <!-- DataContext inherited from the ContentPresenter -->
    </ContentPresenter> 
</TabItem>