如何获取TabControl WPF的TabItem的标题宽度

时间:2015-10-03 19:36:49

标签: c# wpf tabitem actualwidth

我需要做的是在远远超出之前停止GridSplitter,从而隐藏TabControl。因此,我想到的想法是将TabItems的所有标题的ActualWidth的总和绑定到TabControl的MinWidth或保持TabControl的Crid单元格。但问题是到目前为止我无法访问TabItem的标题宽度。我找到的一个解决方案是在Tabitem.Header中放置一个TextBlock,声明它的宽度并用x:Name命名。但是以这种方式使用宽度并不能给出标题的总宽度包括边距和填充等,因此即使接近准确度也不会起作用。

更新

嗯,这是代码。请注意,我已经实现了其中一个解决方案,但如果选项卡是动态加载的,则它不会控制MinWidth。

<Grid Background="#FFD6DBE9" Height="614" Width="1109">
        <Grid.RowDefinitions>
            <RowDefinition Height="89"/>
            <RowDefinition Height="Auto" MinHeight="{Binding ActualHeight, ElementName=gridNotificationsHeader}"/>
            <RowDefinition Height="494*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400*" MinWidth="{Binding MinWidth, ElementName=tabDataEntities}"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="144*">
                <ColumnDefinition.MinWidth>
                    <MultiBinding Converter="{StaticResource StringSumtoIntConvert}">
                        <Binding ElementName="cdLblNotificationsHeader" Path="MinWidth"/>
                        <Binding ElementName="cdBtnNotificationsClose" Path="ActualWidth"/>
                    </MultiBinding>
                </ColumnDefinition.MinWidth>
            </ColumnDefinition>

        </Grid.ColumnDefinitions>
        <GridSplitter x:Name="gridSplitter" Grid.Column="1" HorizontalAlignment="Center" Grid.Row="1" Width="2" Grid.RowSpan="2"/>
        <Grid x:Name="gridNotificationsHeader" Grid.Column="2" Background="#FF657695" 
          Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="cdLblNotificationsHeader" MinWidth="{Binding Width, ElementName=lblNotificationsHeader}"/>
                <ColumnDefinition x:Name="cdBtnNotificationsClose" Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Label x:Name="lblNotificationsHeader" Content="Notifications" VerticalAlignment="Top" 
               FontSize="14.667" Height="30" Foreground="#FFEBF0EE" HorizontalAlignment="Left" Width="92"/>
            <Button x:Name="btnNotificationsClose" Content="X" 
                Margin="0,5,8,0" VerticalAlignment="Top" Width="20" FontFamily="Verdana" HorizontalAlignment="Right" Background="Transparent" FontSize="13.333" Foreground="Black" Grid.Column="1"/>
        </Grid>
        <TabControl x:Name="tabDataEntities" Margin="0,0,5,10" Grid.Row="1" Grid.RowSpan="2" FontSize="12" Grid.ColumnSpan="1" MinWidth="{Binding ElementName=TabItemOne, Path=ActualWidth}">
            <TabItem x:Name="TabItemOne">
                <TabItem.Header>Tab Item</TabItem.Header>
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>
    </Grid>

2 个答案:

答案 0 :(得分:2)

就这么简单

<StackPanel>
    <TabControl>
        <TabItem Header="Hello world" Name="Tab1"/>
        <TabItem Header="Hello" Name="Tab2"/>
        <TabItem Header="world" Name="Tab3"/>
    </TabControl>
    <TextBlock Text="{Binding ElementName=Tab1, Path=ActualWidth}"/>
    <TextBlock Text="{Binding ElementName=Tab2, Path=ActualWidth}"/>
    <TextBlock Text="{Binding ElementName=Tab3, Path=ActualWidth}"/>
</StackPanel>

答案 1 :(得分:2)

做以下AttachedProperty只是有点乐趣:

XAML用法

<TabControl question32926699:TabControlHeaderWidthWatcher.WatchHeadersWidth="true"
            question32926699:TabControlHeaderWidthWatcher.TotalHeadersWidth="{Binding TotalWidth, Mode=OneWayToSource}">
  <TabItem Header="Tab Item 1" />
  <TabItem Header="Tab Item 2" />
</TabControl>

附加财产

public class TabControlHeaderWidthWatcher
{
    private static TabControl m_tabControl;

    public static readonly DependencyProperty WatchHeadersWidthProperty = DependencyProperty.RegisterAttached(
        "WatchHeadersWidth", typeof (bool), typeof (TabControlHeaderWidthWatcher), new PropertyMetadata(default(bool), PropertyChangedCallback));

    public static void SetWatchHeadersWidth(DependencyObject element, bool value)
    {
        element.SetValue(WatchHeadersWidthProperty, value);
    }

    public static bool GetWatchHeadersWidth(DependencyObject element)
    {
        return (bool)element.GetValue(WatchHeadersWidthProperty);
    }

    public static readonly DependencyProperty TotalHeadersWidthProperty = DependencyProperty.RegisterAttached(
        "TotalHeadersWidth", typeof (double), typeof (TabControlHeaderWidthWatcher), new PropertyMetadata(default(double)));

    public static void SetTotalHeadersWidth(DependencyObject element, double value)
    {
        element.SetValue(TotalHeadersWidthProperty, value);
    }

    public static double GetTotalHeadersWidth(DependencyObject element)
    {
        return (double) element.GetValue(TotalHeadersWidthProperty);
    }

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        m_tabControl = dependencyObject as TabControl;
        if (m_tabControl == null) return;

        ((INotifyCollectionChanged)m_tabControl.Items).CollectionChanged += CollectionChanged;
    }

    private static void CollectionChanged(object sender, EventArgs eventArgs)
    {
        foreach (var item in m_tabControl.Items)
        {
            var tabItem = item as TabItem;
            if (tabItem == null) continue;

            // Unsubscribe first in case it was there previously
            tabItem.SizeChanged -= TabItemOnSizeChanged;
            tabItem.SizeChanged += TabItemOnSizeChanged;
        }
    }

    private static void TabItemOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
    {
        var totalWidth = 0.0;
        foreach (var item in m_tabControl.Items)
        {
            var tabItem = item as TabItem;
            if (tabItem == null) continue;

            totalWidth += tabItem.ActualWidth;
        }

        // When more than one row of tabs, the width of the TabControl is used
        var actualWidth = totalWidth > m_tabControl.ActualWidth ? m_tabControl.ActualWidth : totalWidth;
        SetTotalHeadersWidth(m_tabControl, actualWidth);
    }
}

即使您使用ItemsSource的{​​{1}}动态加载标签,此解决方案仍然有效。除非标签包含在多行中,否则TabControl将始终收到总标题宽度。在这种情况下,它将使用TotalHeadersWidth本身的ActualWidth,在您的情况下,它会给出我们想要的内容。