C# 在WPF MVVM应用程序中的选项卡之间正确导航
我正在使用m-V-VM模式(如果相关的话,我正在使用galasoft)执行WPF应用程序,但在tabcontrol中导航时遇到问题。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
我正在跑步时添加标签。所有的绑定似乎都进行得很顺利:在选项卡内部或选项卡的标题中。 我已将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>