2013-03-21 39 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}}" /> 

使用自定义转换器插在上面的结合,你可以显示任何你想要的。

相关问题