简体   繁体   中英

WPF TabControl with a fixed height

I am trying to create a generic dialog which is paged using a TabControl. The dialog has SizeToContent="true" so that the dialog has no unused white-space. The TabControl uses the ItemsSource to set the page content from the model and a ContentTemplateSelector to select the page layout.

The problem I am having is the SizeToContent effect is causing the dialog to resize every time the TabControl.SelectedItem changes where I would rather the dialog sized itself using the content from the largest TabItem.

I've tried using SharedSizeGroup option but this doesn't work. I think this is because a TabControl with an ItemsSource and a ContentTemplateSelector will load the selected tab only and discards the rest, so there is only ever one element of the SharedSizeGroup that is instantiated at one time.

This article offers another solution where each TabItem is measured but this solution doesn't work for me because I am using an ItemsSource and reading the Items collection returns my model objects and not TabItems.

If anyone can offer a solution to this I would be very grateful.

Sphinxxx,

Thanks for the answer which solves the problem of making sure all tabs are created at runtime. However this does not solve the problem of sizing the tabcontrol to the largest content. In fact, the following code using SharedSizeGroup doesn't even work because the SizeToContent of the window seems to override the grid sizing:

<Window x:Class="TestTabControl.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" SizeToContent="Height">
<Grid>
<TabControl Grid.IsSharedSizeScope="True">
  <TabItem Header="Tab 1">
    <Grid >
      <Grid.RowDefinitions>
        <RowDefinition SharedSizeGroup="xxx"/>
      </Grid.RowDefinitions>
      <TextBlock Text="dhuehdiueh dhuehdiueh dhuehdiueh dhuehdiueh dhuehdiueh dhuehdiueh " TextWrapping="Wrap"/>
    </Grid>
  </TabItem>
  <TabItem Header="Tab 2">
    <Grid >
      <Grid.RowDefinitions>
        <RowDefinition SharedSizeGroup="xxx"/>
      </Grid.RowDefinitions>
      <TextBlock Text="ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi ieiureijdi " TextWrapping="Wrap"/>
    </Grid>
  </TabItem>
    </TabControl>

I think the ultimate solution (and I'm still working on it) is to use one of the solutions provided in your link to create all tabs at runtime, combined with some code that measures the content of each tab once loaded. Something like this:

private void LoadedTabControl_Loaded(object sender, RoutedEventArgs e)
{
  double contentWidth = ((FrameworkElement)((TabItem)tabCtrl.SelectedItem).Content).ActualWidth;

  double max = 0;
  foreach (TabItem tab in tabCtrl.Items)
  {
    ((FrameworkElement)tab.Content).Measure(new Size(contentWidth, double.PositiveInfinity));
    max = Math.Max(((FrameworkElement)tab.Content).DesiredSize.Height, max);
  }
  foreach (TabItem tab in tabCtrl.Items)
  {
    ((FrameworkElement)tab.Content).Height = max;
  }
}

Yes, in your case the TabControl only creates UI for one item ( SelectedItem ) at a time. This CodeProject article has links to a few workarounds, and also suggests its own solution:

WPF TabControl: Turning Off Tab Virtualization

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM