2011-01-28 49 views

回答

4

您可以在Template TabItem中添加某种关闭按钮,您可以在后面的代码中关闭该按钮以关闭当前选定的选项卡。

<Style TargetType="TabItem"> 
      <Setter.Value> 
       <ControlTemplate TargetType="sdk:TabItem"> 
          <Button x:Name="PART_btnClose" 
              Height="15" 
              Width="15" 
              Grid.Column="1" 
              HorizontalAlignment="Right" 
              VerticalAlignment="Center" 
              Margin="20,0,3,8" BorderThickness="1" Cursor="Hand" /> 
</ControlTemplate> 
</Setter.Value> 
</Style> 

在此之后,在应用模板,你可以订阅ButtonClicked事件。

事情是这样的:

public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     PART_btnClose = GetTemplateChild("PART_btnClose") as Button; 

     if (PART_btnClose != null) 
     { 
      PART_btnClose.Click += new RoutedEventHandler(PART_btnClose_Click); 
     } 

在这种情况下,您可以关闭选项卡。

希望这会有所帮助,代码可能无法正常工作,只是做得很快。

泰Rozak

+0

谢谢您的回答。你能否详细说明这应该如何工作?如果我创建了一个扩展TabItem的TabItemExt类,我可以重写OnApplyTemplate并按照你所说的去做。但我还需要一个TabControlExt扩展TabControl,它可以在内部使用这个新的TabItemExt而不是通常的TabItem。我该怎么做呢?许多感谢 – Houman 2011-01-29 17:28:57

5

我以前有同样的问题,然后我决定使用扩展TabControl。我不知道我在哪里找到它,但没关系,现在它在我的项目中。

有了这个TabControl我可以添加或删除ViewModel集合中的项目,我的更改将反映在用户界面上。

MyTabControl.cs

public class MyTabControl : TabControl 
{ 
    public MyTabControl() 
     : base() 
    { 
     this.SelectionChanged += OnSelectionChanged; 
    } 

    #region Tabs with databinding and templates 
    /// <summary> 
    /// Template for a TabItem header 
    /// </summary> 
    public DataTemplate TabHeaderItemTemplate 
    { 
     get { return (DataTemplate)GetValue(TabHeaderItemTemplateProperty); } 
     set { SetValue(TabHeaderItemTemplateProperty, value); } 
    } 
    public static readonly DependencyProperty TabHeaderItemTemplateProperty = 
     DependencyProperty.Register("TabHeaderItemTemplate", typeof(DataTemplate), typeof(MyTabControl), new PropertyMetadata(
      (sender, e) => 
      { 
       ((MyTabControl)sender).InitTabs(); 
      })); 

    /// <summary> 
    /// Template for a content 
    /// </summary> 
    public DataTemplate TabItemTemplate 
    { 
     get { return (DataTemplate)GetValue(TabItemTemplateProperty); } 
     set { SetValue(TabItemTemplateProperty, value); } 
    } 
    public static readonly DependencyProperty TabItemTemplateProperty = 
     DependencyProperty.Register("TabItemTemplate", typeof(DataTemplate), typeof(MyTabControl), new PropertyMetadata(
      (sender, e) => 
      { 
       ((MyTabControl)sender).InitTabs(); 
      })); 

    /// <summary> 
    /// Source of clr-objects 
    /// </summary> 
    public IEnumerable MyItemsSource 
    { 
     get 
     { 
      return (IEnumerable)GetValue(MyItemsSourceProperty); 
     } 
     set 
     { 
      SetValue(MyItemsSourceProperty, value); 
     } 
    } 

    public static readonly DependencyProperty MyItemsSourceProperty = 
     DependencyProperty.Register("MyItemsSource", typeof(IEnumerable), typeof(MyTabControl), new PropertyMetadata(
      (sender, e) => 
      { 
       MyTabControl control = (MyTabControl)sender; 
       INotifyCollectionChanged incc = e.OldValue as INotifyCollectionChanged; 
       if (incc != null) 
       { 
        incc.CollectionChanged -= control.MyItemsSourceCollectionChanged; 
       } 
       control.InitTabs(); 

       incc = e.NewValue as INotifyCollectionChanged; 
       if (incc != null) 
       { 
        incc.CollectionChanged += control.MyItemsSourceCollectionChanged; 
       } 
      })); 


    /// <summary> 
    /// Selected item as object 
    /// </summary> 
    public object MySelectedItem 
    { 
     get { return (object)GetValue(MySelectedItemProperty); } 
     set { SetValue(MySelectedItemProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for MySelectedItem. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty MySelectedItemProperty = 
     DependencyProperty.Register("MySelectedItem", typeof(object), typeof(MyTabControl), new PropertyMetadata(
      (sender, e) => 
      { 
       MyTabControl control = (MyTabControl)sender; 

       if (e.NewValue == null) 
        control.SelectedItem = null; 
       else 
       { 
        var tab = control.Items.Cast<TabItem>().FirstOrDefault(ti => ti.DataContext == e.NewValue); 
        if (tab != null && control.SelectedItem != tab) 
         control.SelectedItem = tab; 
       } 
      })); 

    private void InitTabs() 
    { 
     Items.Clear(); 
     if (MyItemsSource != null && MyItemsSource.OfType<object>().Any()) 
     { 
      int i = 0; 
      foreach (var item in MyItemsSource) 
      { 
       var newitem = new TabItem(); 

       if (TabItemTemplate != null) 
        newitem.Content = TabItemTemplate.LoadContent(); 

       if (TabHeaderItemTemplate != null) 
        newitem.Header = TabHeaderItemTemplate.LoadContent(); 

       newitem.DataContext = item; 
       Items.Add(newitem); 
      } 
      VisualStateManager.GoToState(this, "Normal", true); 
     } 
     else VisualStateManager.GoToState(this, "NoTabs", true); 
    } 

    private void MyItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      if (e.NewStartingIndex > -1) 
      { 
       foreach (var item in e.NewItems) 
       { 
        var newitem = new TabItem(); 

        if (TabItemTemplate != null) 
         newitem.Content = TabItemTemplate.LoadContent(); 

        if (TabHeaderItemTemplate != null) 
         newitem.Header = TabHeaderItemTemplate.LoadContent(); 

        newitem.DataContext = item; 
        Items.Add(newitem); 
       } 
      } 
     } 
     else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) 
     { 
      if (e.OldStartingIndex > -1) 
      { 
       var ti = (TabItem)this.Items[e.OldStartingIndex]; 
       Items.RemoveAt(e.OldStartingIndex); 
      } 
     } 
     else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace) 
     { 
      Items.RemoveAt(e.OldStartingIndex); 

      var newitem = new TabItem(); 

      if (TabItemTemplate != null) 
       newitem.Content = TabItemTemplate.LoadContent(); 

      if (TabHeaderItemTemplate != null) 
       newitem.Header = TabHeaderItemTemplate.LoadContent(); 

      newitem.DataContext = e.NewItems[0]; 

      Items.Add(newitem); 
      Items.Insert(e.NewStartingIndex, newitem); 
     } 
     else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset) 
     { 
      InitTabs(); 
     } 
    } 

    #endregion 

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     var si = e.AddedItems.Cast<TabItem>().FirstOrDefault(); 
     if (si != null) 
      this.MySelectedItem = si.DataContext; 
     else this.MySelectedItem = null; 
    } 
} 

MainPage.xaml中

<my:MyTabControl MyItemsSource="{Binding Items}" MySelectedItem="{Binding SelectedITem}"> 
     <my:MyTabControl.TabHeaderItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock Text="{Binding Title}" VerticalAlignment="Center"/> 
        <Button Content="X" Margin="3" Width="20" Height="20" Grid.Column="1" 
          Command="{Binding RequestCloseCommand}"/> 
       </Grid> 
      </DataTemplate> 
     </my:MyTabControl.TabHeaderItemTemplate> 
     <my:MyTabControl.TabItemTemplate> 
      <DataTemplate> 
       <ContentControl Content="{Binding Content}"/> 
      </DataTemplate> 
     </my:MyTabControl.TabItemTemplate> 
    </my:MyTabControl> 

注意,该特性被称为MyItemsSourceMySelectedItem,因为这TabControl使用对象,而不是TabItem

和两个的ViewModels: MainViewModel.cs

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     this.Items = new ObservableCollection<TabItemViewModel> 
         { 
          new TabItemViewModel("Tab 1", OnItemRequestClose), 
          new TabItemViewModel("Tab item 2", OnItemRequestClose) 
         }; 
    } 

    public ObservableCollection<TabItemViewModel> Items { get; set; } 

    public void OnItemRequestClose(TabItemViewModel item) 
    { 
     this.Items.Remove(item); 
    } 
} 

TabItemViewModel.cs

public class TabItemViewModel 
{ 
    public TabItemViewModel(string title, Action<TabItemViewModel> onClose) 
    { 
     this.Title = title; 
     this.RequestCloseCommand = new DelegateCommand(_ => onClose(this)); 

     //Just a demontration 
     this.Content = "Test content "+title; 
    } 

    public string Title { get; set; } 

    public ICommand RequestCloseCommand { get; set; } 

    public object Content { get; set; }  
}