2012-07-17 43 views
1

在我看來,我在動態添加自定義TabItems(TextseiteTabItem)。通過DataContext屬性,我爲每個TabItem提供了一個模型來處理(填充值)。現在我添加了一個關閉命令到自定義TabItems,但它不會工作。我無法設法發送關閉命令給視圖模型。以上是我的嘗試..如何關閉MVVM Light中的TabItem

我自定義的TabItem:

<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItem" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      mc:Ignorable="d" 
      xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" 
      xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
      xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"> 

    <sdk:TabItem.Header> 
     <StackPanel Orientation="Horizontal"> 
      <sdk:Label Content="{Binding Seitennummer, StringFormat='Seite {0}', Mode=TwoWay}"/> 
      <Button Content="X" 
        Command="{Binding CloseTabCommand, Mode=TwoWay}" 
        DataContext="{Binding ElementName=TemplateTabControl}" 
        CommandParameter="{Binding SelectedItem, ElementName=TemplateTabControl}" /> 
     </StackPanel> 
    </sdk:TabItem.Header> 

    <sdk:TabItem.Content> 
     <Grid x:Name="LayoutRoot"> 
      ... 
     </Grid> 
    </sdk:TabItem.Content> 
</sdk:TabItem> 

在我看來:

... 
<sdk:TabControl toolkit:DockPanel.Dock="Bottom" ItemsSource="{Binding Tabs}" x:Name="TemplateTabControl"/> 
... 

在我的ViewModel:

public class PortfolioViewModel : ViewModelBase 
{ 
    public ObservableCollection<TabItem> Tabs { get; set; } 

    public RelayCommand<TabItem> CloseTabCommand 
    { 
     get; 
     private set; 
    } 

    public PortfolioViewModel() 
    { 
     CloseTabCommand = new RelayCommand<TabItem>(tab => 
     { 
      //never reached 
     }, 
     tab => 
     { 
      //never reached 
     }); 

     Tabs = new ObservableCollection<TabItem>(); 

     AddTextseite(); 
     AddTextseite();   
    } 

    void AddTextseite() 
    { 
     TabItem item = new TextseiteTabItem(); 
     item.DataContext = new TextSeiteModel(); 

     Tabs.Add(item); 
    } 

} 
+0

綁定您的TabControl.ItemsSource到一系列模型。每個選項卡在模型添加到集合時出現。刪除模型時,每個選項卡都會消失。 VM不應該做任何UI工作。 – Will 2012-07-17 14:14:26

回答

0

這是我解決這個問題的方法。我承認這不是一個好的解決方案,並打破了mvvm模式,但是@herzmeister說現在其他方法對我的項目來說太精細了。 (但它不會是最終的解決方案;-))

TabItemViewModel:

public delegate void CloseTabItemHandler(); 

public class TextseiteTabItemViewModel : ViewModelBase 
{ 
    public event CloseTabItemHandler CloseTabItem; 
    public RelayCommand CloseTabCommand {get; set;} 

    public TextseiteTabItemViewModel() 
    { 
     CloseTabCommand = new RelayCommand(() => 
     { 
      if (CloseTabItem == null) return; 
      CloseTabItem(); 
     }); 
    } 
} 

TabItemView:

<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItemView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d" 
     xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" 
     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
     xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"> 

    <sdk:TabItem.Header> 
     <StackPanel Orientation="Horizontal"> 
      <Button Content="X" Command="{Binding CloseTabCommand, Mode=TwoWay}" /> 
     </StackPanel> 
    </sdk:TabItem.Header> 

    <sdk:TabItem.Content> 
     <Grid x:Name="LayoutRoot"> 
      ... 
     </Grid> 
    </sdk:TabItem.Content> 
</sdk:TabItem> 

父視圖模型:

public class PortfolioViewModel : ViewModelBase 
{ 
    public ObservableCollection<TabItem> Tabs { get; set; } 

    public PortfolioViewModel() 
    { 
     Tabs = new ObservableCollection<TabItem>(); 

     AddTextseite(); 
     AddTextseite(); 
    } 

    void AddTextseite() 
    { 
     var viewmodel = new TextseiteTabItemViewModel(); 

     TabItem item = new TextseiteTabItemView(); 
     item.DataContext = viewmodel; 

     viewmodel.CloseTabItem += new CloseTabItemHandler(() => 
     { 
      Tabs.Remove(item); 
     }); 

     Tabs.Add(item); 
    } 
} 
1

您正試圖使用​​MVVM但我看到的奇怪的東西是你的視圖模型中的UI元素(Tabs)的集合。正確的方法是創建描述Tab項並在那裏移動命令的ViewModel。然後它會綁定。要從標籤中刪除標籤,您應該在標籤視圖模型中公開事件,並將其附加到窗體PortfolioViewModel。

當然,我的更改會導致您的TextseiteTabItem不會顯示在TablControl中。但是可以使用TabControl.ItemTemplate和TabControl.ContentTemplate輕鬆修復它。

1

首先,您的CloseTabCommand在您當前的代碼片段中不做任何事情://never reached。執行處理程序應該讀取類似tab.Visibility = Visibility.CollapsedmyTabControl.Items.Remove(myTabItem)。其次,正如@Rafal指出的那樣,在ViewModel中使用UI元素並不是實現MVVM的正確方法。如果您想要可關閉的選項卡項目,則正確的方法是導出一個通用的CloseableTabItem控件或在UI層上使用可設置的ICommand CloseCommand編寫ClosableTabItemBehavior,該設置可綁定到ViewModel上對應的ICommand實例。誠然,這種方法可能對你的項目來說太精細了。

0

here你可以找到一個演示應用程序,可關閉wpf標籤,也許它適用於你的silverlight版本。