2013-03-21 43 views
5

我有1周... N在我的應用程序的TabControls,用下面的XAML設置:顯示的SelectedIndex

<TabControl Name="ordersTabControl" ItemsSource="{Binding CoilItems}"> 
    <TabControl.ItemTemplate> 
    <DataTemplate DataType="models:Coil"> 
     <StackPanel> 
     <TextBlock Text="{Binding CoilCode, StringFormat='Coil: {0}'}" /> 
     <TextBlock Text="{Binding ArticleCode, StringFormat='Auftrag: {0}'}" /> 
     <TextBlock Text="{Binding RestWeight, StringFormat='Restgewicht: {0} kg'}" /> 
     </StackPanel> 
    </DataTemplate> 
    </TabControl.ItemTemplate> 
    <TabControl.ContentTemplate> 
    [...] 
    </TabControl.ContentTemplate> 
</TabControl> 

在運行時打開的選項卡的變化量。現在,我想在每個標籤中顯示一個索引(即第一個標籤顯示「Order 1」,第二個「Order 2」等等)以及每個標頭中已有的信息。

AFAIK使用DataTemplate時我無法通過代碼隱藏訪問tab-屬性,那麼在XAML中是否有任何方法來綁定tabheader內的textblock以顯示tabcontrol中該特定選項卡的索引?

我覺得應該可以用的RelativeSource和FindAncestors?唉,我真的無法找到有關這些設置的任何明確的教程(並且我僅在2天前開始使用WPF)。

+1

如果你可以在視圖模型中包含'models:Coil'對象,比如'CoilViewModel',那麼你可以添加一個名爲CoilIndex的附加屬性,並且允許你添加一個綁定到該索引的'TextBlock',例如。 '' – 2013-03-21 19:28:13

回答

2

我要給你使用附加屬性的解決方案。檢查代碼:

附加屬性

public static class IndexAttachedProperty 
{ 


    #region TabItemIndex 

    public static int GetTabItemIndex(DependencyObject obj) 
    { 
     return (int) obj.GetValue(TabItemIndexProperty); 
    } 

    public static void SetTabItemIndex(DependencyObject obj, int value) 
    { 
     obj.SetValue(TabItemIndexProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for TabItemIndex. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty TabItemIndexProperty = 
     DependencyProperty.RegisterAttached("TabItemIndex", typeof (int), typeof (IndexAttachedProperty), 
              new PropertyMetadata(-1)); 



    #endregion 

    #region TrackTabItemIndex 

    public static bool GetTrackTabItemIndex(DependencyObject obj) 
    { 
     return (bool) obj.GetValue(TrackTabItemIndexProperty); 
    } 

    public static void SetTrackTabItemIndex(DependencyObject obj, bool value) 
    { 
     obj.SetValue(TrackTabItemIndexProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for TrackTabItemIndex. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty TrackTabItemIndexProperty = 
     DependencyProperty.RegisterAttached("TrackTabItemIndex", typeof (bool), typeof (IndexAttachedProperty), 
              new PropertyMetadata(false, TrackTabItemIndexOnPropertyChanged)); 

    private static void TrackTabItemIndexOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var tabControl = GetParent(d, p => p is TabControl) as TabControl; 
     var tabItem = GetParent(d, p => p is TabItem) as TabItem; 
     if (tabControl == null || tabItem == null) 
      return; 
     if (!(bool)e.NewValue) 
      return; 
     int index = tabControl.Items.IndexOf(tabItem.DataContext == null ? tabItem : tabItem.DataContext); 
     SetTabItemIndex(d, index); 
    } 
    #endregion 





    public static DependencyObject GetParent(DependencyObject item, Func<DependencyObject, bool> condition) 
    { 
     if (item == null) 
      return null; 
     return condition(item) ? item : GetParent(VisualTreeHelper.GetParent(item), condition); 
    } 
} 

該代碼定義了兩個附加屬性,第一個是,如果一個項目跟蹤它包含在至極所述的標籤項索引來設置。第二個是索引屬性。

XAML樣品的編號:

 <TabControl.ItemTemplate> 
      <DataTemplate DataType="{x:Type WpfApplication3:A}"> 
       <StackPanel x:Name="tabItemRoot" WpfApplication3:IndexAttachedProperty.TrackTabItemIndex ="True"> 
        <TextBlock Text="{Binding Text}"/> 
        <TextBlock Text="{Binding Path=(WpfApplication3:IndexAttachedProperty.TabItemIndex), ElementName=tabItemRoot}"/> 

       </StackPanel> 
      </DataTemplate> 
     </TabControl.ItemTemplate> 

上面的代碼是使用附加屬性的例子。您可以輕鬆適應您的代碼。

結果:

enter image description here

希望此代碼對你的作品...

+1

這很好,非常感謝! – 2013-03-22 10:05:14

1

即使您有權訪問代碼隱藏中的TabItem屬性,它也無濟於事,因爲該選項卡並不知道它是TabControl集合中的自己的索引。這是所有ItemsControls的真實,似乎煩人,但它是有道理的,因爲當可以在任何物體告訴過你自己的位置,是一家集內呢?

它可與的IndexOf來完成,但是,只要你有機會獲得這兩個控件的​​和選項卡的內容。我們可以在MultiValueConverter做到這一點,以便它可以在DataTemplate中內完成。

轉換代碼:

public class ItemsControlIndexConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
     ItemCollection itemCollection = (ItemCollection)values[0]; 
     return (itemCollection.IndexOf(values[1]) + 1).ToString(); 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
     { 
     throw new NotImplementedException(); 
     } 
    } 

TabControl的XAML:

<TabControl ItemsSource="{Binding CoilItems}"> 
    <TabControl.Resources> 
     <local:ItemsControlIndexConverter x:Key="IndexConverter"/> 
    </TabControl.Resources> 
    <TabControl.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock> 
        <TextBlock.Text> 
         <MultiBinding Converter="{StaticResource IndexConverter}" StringFormat="Order {0}" Mode="OneWay"> 
          <Binding RelativeSource="{RelativeSource AncestorType=TabControl}" Path="Items"/> <!-- First converter index is the ItemsCollection --> 
          <Binding /> <!-- Second index is the content of this tab --> 
         </MultiBinding> 
        </TextBlock.Text> 
       </TextBlock> 
       <!-- Fill in the rest of the header template --> 
      </StackPanel> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
</TabControl> 
2

如果你不使用AlternationCount財產挪作他用,你可以破解它一個簡單的解決方案。

綁定AlternationCount這樣

<TabControl AlternationCount="{Binding Path=Items.Count, RelativeSource={RelativeSource Self}}"> 

然後在你的ItemTemplate綁定TextBlock的或希望的AlternationIndex這樣的其它控制,

<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem}}" /> 

使用自定義轉換器插在上面的結合,你可以顯示任何你想要的。

相關問題