5

次の XAML セットアップを使用して、アプリケーションに 1...n 個のタブ コントロールがあります。

<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>

開いているタブの量は実行時に変化します。ここで、各ヘッダーに既にある情報に加えて、各タブにインデックスを表示したいと思います (つまり、最初のタブには「注文 1」、2 番目のタブには「注文 2」などを表示します)。

私の知る限り、DataTemplate を使用している場合、コード ビハインドを介してタブ プロパティにアクセスすることはできません。そのため、XAML でタブ ヘッダー内のテキスト ブロックをバインドして、その特定のタブのインデックスをタブ コントロールに表示する方法はありますか?

RelativeSource と FindAncestors で可能だと思いますか? 残念ながら、これらの設定に関する明確なチュートリアルを実際に見つけることができませんでした (そして、2 日前に WPF を使い始めたばかりです)。

4

3 に答える 3

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}}" />

上記のバインディングにプラグインされたカスタム コンバーターを使用すると、必要なものを表示できます。

于 2013-03-24T15:55:09.910 に答える
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);
    }
}

このコードは 2 つの添付プロパティを定義します。最初のプロパティは、アイテムが含まれているタブ アイテム インデックスを追跡するかどうかを設定します。2 つ目は index プロパティです。

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>

上記のコードは、添付プロパティを使用する例です。コードに簡単に適応できます。

結果:

ここに画像の説明を入力

このコードがうまくいくことを願っています...

于 2013-03-21T20:15:38.280 に答える
1

コードビハインドのプロパティだけにアクセスできたとしても、タブはコレクションTabItem内の独自のインデックスを認識していないため、役に立ちません。TabControlこれはすべてItemsControlsに当てはまり、煩わしいように見えますが、コレクション内での自身の位置がいつオブジェクトであるかを教えてくれるので、それは理にかなっています。

ItemsCollectionただし、コントロールとタブのコンテンツの両方にアクセスできる限り、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>
于 2013-03-21T19:01:21.893 に答える