对我来说,这听起来不像 MVVM。我们使用 数据,而不是 UI 元素。我们使用包含满足某些要求所需的所有属性的类集合,并将这些属性数据绑定到DataTemplates 中的 UI 控件。这样,我们通过将数据项添加到这些集合中来添加 UI 控件,并让出色的 WPF 模板系统处理 UI。
例如,您有一个 TabControl,我们希望以适当的 MVVM 方式从...中添加或删除 TabItems。首先,我们需要一个可以代表每个TabItem的项目集合:
public static DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(TestView));
public ObservableCollection<string> Items
{
get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
我只是使用DependencyProperty,因为我在UserControl 中敲了这个,为了简单起见,我只是使用strings 的集合。您需要创建一个类,其中包含整个TabItem 内容所需的所有数据。接下来我们看看TabControl:
<TabControl ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ItemTemplate}" />
我们将集合数据绑定到TabControl.ItemsSource 属性,并将TabControl.ItemTemplate 设置为名为@987654337@ 的Resource。现在让我们看看:
xmlns:System="clr-namespace:System;assembly=mscorlib"
...
<DataTemplate x:Key="ItemTemplate" DataType="{x:Type System:String}">
<TabItem Header="{Binding}" />
</DataTemplate>
DataTemplate 定义了我们收藏中每件商品的外观。为简单起见,我们的strings 只是绑定到TabItem.Header 属性的数据。这意味着对于我们添加到集合中的每个项目,我们现在将获得一个新的TabItem,其Header 属性设置为string 的值:
Items.Add("Tab 1");
Items.Add("Tab 2");
Items.Add("Tab 3");
请注意,为了完整性,我包含了 System XML 命名空间前缀,但您不需要它,因为您的 DataType 将是您自己的自定义类。你也需要更多DataTemplates。例如,如果您的自定义类有一个Header 属性和一个Content 属性,这是另一个自定义类,假设称为Content,它包含TabItem.Content 属性的所有属性,您可以这样做:
<DataTemplate x:Key="ItemTemplate" DataType="{x:Type YourPrefix:YourClass}">
<TabItem Header="{Binding Header}" Content="{Binding Content}" />
</DataTemplate>
<DataTemplate DataType="{x:Type YourPrefix:Content}">
<YourPrefix:SomeUserControl DataContext="{Binding}" />
</DataTemplate>
所以这会给你TabItems 和Headers 集和来自SomeUserControl 的Content,你可以设计。你不需要使用UserControls,你可以在DataTemplate中添加更多的UI控件。但是您需要在某处添加更多控件...以及更多类和属性,始终记住正确实现基本的INotifyPropertyChanged interface。
最后,要以正确的 MVVM 方式回答您的问题...要删除 TabItem,您只需从集合中删除与该 TabItem 相关的项目。很简单......或者如果你真的像你声称的那样使用 MVVM 的话。正确学习 MVVM 真的很值得,因为您很快就会看到好处。我会让你自己去寻找教程,因为有很多可供选择。
更新>>>
您的事件处理仍然不是那么 MVVM...您不需要在任何地方传递任何视图模型的引用。 MVVM 方式是在视图模型中使用命令。特别是,您应该调查RelayCommand。我有我自己的版本,但是这些命令使我们能够使用视图模型中的方法或内联 delegates(其中 action 和 canExecute 在此示例中为CommandParameter 值):
<Button Content="Close Tab" Command="{Binding CloseTabCommand}"
CommandParameter="{Binding}" />
...
public ICommand CloseTabCommand
{
get { return new ActionCommand(action => Items.Remove(action),
canExecute => canExecute != null && Items.Contains(canExecute)); }
}
所以无论视图模型有你的Tabs 集合,都应该有一个AddTabCommand 和一个CloseTabCommand,它们可以在Tabs 集合中添加和删除项目。但要明确一点,要使其正常工作,您的 ClosableTab 类应该是数据类而不是 UI 控件类。如果是 UI 控件,请使用 DataTemplate 指定它。
您可以在 MSDN 上的 this article 中找到有关 RelayCommand 的信息。