c# - 添加到绑定(bind)的 TabControl (mvvm) 后获取新选项卡的父级

标签 c# wpf mvvm tabcontrol

我正在使用以下指南向我的选项卡添加一个关闭按钮:

http://www.codeproject.com/Articles/84213/How-to-add-a-Close-button-to-a-WPF-TabItem

这已成为一个问题,因为该事件使用添加的选项卡的“父级”从选项卡控件中删除该选项卡。我正在使用 mvvm 绑定(bind)选项卡控件,因此父属性显然没有被设置,并且当事件试图从中删除时给我一个父级的空引用异常。

这是绑定(bind),所以你明白了:

<TabControl Name="tabControl" Margin="0,22,0.2,-5.2" ItemsSource="{Binding Tabs}" Background="#FF4C76B2"/>

这是添加标签的地方。
private void AddTab(object tabName)
{
    ClosableTab newTab = new ClosableTab();
    newTab.Title = "title?";
    //newTab.Header = tabName;
    TextBox test = new TextBox();

    test.Text = "CONTENT (" + tabName + ") GOES HERE";
    newTab.Content = test;

    Tabs.Add(newTab);
    OnPropertyChanged("Tabs");
}

这是发生空引用的事件:
void button_close_Click(object sender, RoutedEventArgs e)
{
    ((TabControl)this.Parent).Items.Remove(this);
}

在我看来,有两种选择:
  • 尝试找到另一种方法来删除标签(没有父
    属性(property))
  • 尝试找到一种方法以某种方式设置父属性(不能
    直接完成,会引发编译器错误)
  • 最佳答案

    对我来说,这听起来不像 MVVM。我们使用数据,而不是 UI 元素。我们使用包含满足某些要求所需的所有属性的类集合,并将这些属性数据绑定(bind)到 DataTemplate 中的 UI 控件。 s。这样,我们通过将数据项添加到这些集合中来添加 UI 控件,并让出色的 WPF 模板系统来处理 UI。

    例如,您有一个 TabControl我们要添加或删除的 TabItem s from ... 以适当的 MVVM 方式。首先,我们需要一组可以代表每个 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 中敲了这个我只是使用 string 的集合s 为简单起见。您需要创建一个包含整个 TabItem 所需的所有数据的类。内容。接下来,我们来看看TabControl :
    <TabControl ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ItemTemplate}" />
    

    我们将集合数据绑定(bind)到 TabControl.ItemsSource属性,我们设置 TabControl.ItemTemplateResource命名为 ItemTemplate .现在让我们看看:
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    ...
    <DataTemplate x:Key="ItemTemplate" DataType="{x:Type System:String}">
        <TabItem Header="{Binding}" />
    </DataTemplate>
    

    这个DataTemplate定义我们集合中的每个项目的外观。为简单起见,我们的 string s 只是绑定(bind)到 TabItem.Header 的数据。属性(property)。这意味着对于我们添加到集合中的每个项目,我们现在将获得一个新的 TabItem及其Header属性设置为 string 的值:
    Items.Add("Tab 1");
    Items.Add("Tab 2");
    Items.Add("Tab 3");
    

    请注意,我包括了 System XML 命名空间前缀以确保完整性,但您不需要它,因为您的 DataType将是您自己的自定义类。你需要更多 DataTemplate也是。例如,如果您的自定义类有 Header属性(property)和 Content属性,这是另一个自定义类,比方说称为 Content ,其中包含 TabItem.Content 的所有属性属性(property),你可以这样做:
    <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>
    

    所以这会给你TabItemHeader s 设置和 Content来自SomeUserControl你可以设计的。您不需要使用 UserControl s,您可以向 DataTemplate 添加更多 UI 控件。 .但是您需要在某处添加更多控件...以及更多类和属性,始终记住正确实现基本的 INotifyPropertyChanged interface .

    最后,以正确的 MVVM 方式回答您的问题...删除 TabItem ,您只需删除与 TabItem 相关的项目从收藏。很简单......或者如果你真的像你声称的那样使用 MVVM 的话。正确学习 MVVM 真的很值得,因为您很快就会看到好处。我会让你找到自己的教程,因为有很多可供选择。

    更新>>>

    您的事件处理仍然不是那么 MVVM...您不需要在任何地方传递任何 View 模型的引用。 MVVM 方式是在 View 模型中使用命令。特别是,您应该调查 RelayCommand .我有自己的版本,但这些命令使我们能够从数据绑定(bind) Button 执行操作s 和其他 UI 控件使用方法或内联 delegate View 模型中的 s(这里的 actioncanExecuteCommandParameter 值):
    <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)); }
    }
    

    所以无论 View 模型有你的Tabs集合应该有 AddTabCommandCloseTabCommandTabs 中添加和删除项目收藏。但要明确一点,要使其正常工作,您的 ClosableTab类应该是数据类而不是 UI 控件类。使用 DataTemplate如果它是 UI 控件,则指定它。

    您可以了解RelayCommand来自 this article在 MSDN 上。

    关于c# - 添加到绑定(bind)的 TabControl (mvvm) 后获取新选项卡的父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21006682/

    相关文章:

    c# - 使用 jquery ajax 在 aspx.cs 文件中调用 webmethod

    c# - Entity Framework 5为空

    WPF Textbox Preview 事件相关

    wpf - 从Freezable派生的WPF对象如何在XAML中卡住?

    c# - 如果属性为空,抛出哪个/何时异常?

    c# - WPF UserControl 检测 LostFocus 忽略 child

    安卓分页 3 : It is possible to get the itemcount from PagingData<T>?

    c# - 编写 MVVM 样板代码的更好方法?

    wpf - 在 WPF ListView 中选择项目时,更新其他控件以查看详细信息

    c# - .NET Double.TryParse(num, format, cultureinfo, out) 错误