我有一个关于将TabControl与mvvm模式一起使用的问题。 以下是我的代码的一些部分:
<UserControl>
<UserControl.DataContext>
<vm:TabsViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles/Converters.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.Resources>
<Style x:Key="TabItemStyle" TargetType="TabItem">
<Setter Property="Header" Value="{Binding Customer.LastName}"/>
<Setter Property="Content" Value="{Binding}"/>
</Style>
<DataTemplate x:Key="TabItemHeaderTemplate">
<TextBlock Text="{Binding}" FontWeight="Medium"/>
</DataTemplate>
<DataTemplate x:Key="TabItemContentTemplate" x:Shared="false">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GroupBox Header="Info">
<StackPanel Orientation="Horizontal" Grid.Column="0">
<TextBlock Text="{Binding Customer.FullName}" />
</StackPanel>
</GroupBox>
<GroupBox Header="Finances" Grid.Column="1" >
<controls:CustomerFinancesView DataContextChanged="CustomerFinancesView_DataContextChanged">
<controls:CustomerFinancesView.DataContext>
<vm:FinancesViewModel />
</controls:CustomerFinancesView.DataContext>
</controls:CustomerFinancesView>
</GroupBox>
</Grid>
</DataTemplate>
</Grid.Resources>
<TabControl
ItemsSource="{Binding Tabs, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding CurrentTab, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemContainerStyle="{StaticResource TabItemStyle}"
ItemTemplate="{StaticResource TabItemHeaderTemplate}"
ContentTemplate="{StaticResource TabItemContentTemplate}"/>
</Grid>
</UserControl>
底层视图模型提供了添加或删除选项卡的方法和命令。像这样:
public class TabsViewModel : InteractableModel
{
ObservableCollection<TabModel> _tabs = new ObservableCollection<TabModel>();
public ObservableCollection<TabModel> Tabs
{
get
{
return _tabs;
}
set
{
if (_tabs == value)
return;
_tabs = value;
OnPropertyChanged("Tabs");
}
}
private TabModel _currentTab;
public TabModel CurrentTab
{
get { return _currentTab; }
set
{
if (_currentTab == value)
return;
_currentTab = value;
OnPropertyChanged("CurrentTab");
}
}
public TabsViewModel()
{
...
}
void OpenTab(Customer customer)
{
var existedTab = Tabs.FirstOrDefault(t=>t.Customer.ID == customer.ID);
if (existedTab != null)
{
existedTab.Refresh();
CurrentTab = existedTab;
}
else
{
var newTab = new TabModel(customer);
Tabs.Add(newTab);
CurrentTab = newTab;
}
}
void RemoveTab(object param)
{
var tabToRemove = Tabs.ElementAtOrDefault((int)param);
if (tabToRemove != null)
{
Tabs.Remove(tabToRemove);
}
}
}
}
如您所见,每个TabItem的内容由TabItemContentTemplate DataTemplate模板化。此DataTemplate包含UserControl。假设这只是来自VS模板的空用户控件。 当我打开第一个选项卡时 - 调用此控件ctor,相应的viewmodel创建,并引发DataContextChanged事件。但打开任何其他选项卡,或重新打开此选项卡不会影响创建此UserControl - 它仍然是为第一个选项卡打开创建的控件实例。 viewmodel(未调用ctor)和事件(不提升)也是如此。 请帮助我找到一种方法,每当我打开标签时从datatemplate实例化这个用户控件(或者每当我打开新标签时;两种变体都适合)并在每次关闭标签时将其销毁。我已经阅读了很多关于此的文章,但我发现只有使用
x:Shared=false
在DataTemplate上。但是这种解决方法对我不起作用。
P.S。我的最终目标是使用mvvm模式向DataTemplate的内部UserControl提供特定于Tab的数据。 (每个选项卡都存储了很多信息。这些信息被分成用户控件和它自己的视图模型。我想通过将每个选项卡控件绑定到当前选项卡模型来自定义每个选项卡控件的显示数据。如下所示:TabsViewModel存储集合; TabModel存储模型, Control1VM(Model),Control2VM(Model),...)