Как я могу заставить расширитель WPF растягиваться?

StackOverflow https://stackoverflow.com/questions/680498

  •  22-08-2019
  •  | 
  •  

Вопрос

В Expander элемент управления в WPF не растягивается, чтобы заполнить все доступное пространство.Есть ли какие-либо решения в XAML для этого?

Это было полезно?

Решение

Все, что вам нужно сделать, это это:

<Expander>
  <Expander.Header>
    <TextBlock
      Text="I am header text..."
      Background="Blue"
      Width="{Binding
        RelativeSource={RelativeSource
          Mode=FindAncestor,
          AncestorType={x:Type Expander}},
        Path=ActualWidth}"
      />
  </Expander.Header>
  <TextBlock Background="Red">
    I am some content...
  </TextBlock>
</Expander>

http://joshsmithonwpf.wordpress.com/2007/02/24/stretching-content-in-an-expander-header/

Другие советы

Не растягивается Expanderобычно это проблема с нерастягиваемыми родительскими элементами управления..Возможно, один из родительских элементов управления определил HorizontalAlignment или VerticalAlignment собственность?

Если вы можете опубликовать какой-нибудь пример кода, мы сможем дать вам лучший ответ.

Это решение намного проще и не влияет на другие элементы управления expander, которые вы можете использовать в своем приложении.

  <Expander ExpandDirection="Right" Grid.Column="0" Name="topOfB"> 
    <Expander.Header>
        <Grid HorizontalAlignment="Stretch" Width="{Binding Path=ActualWidth, ElementName=topOfB}">
            <!-- control content goes here -->

Принятый ответ выводится за пределы элемента управления, поскольку содержимое заголовка находится в одном столбце, а кнопка расширения - в первом.Может быть, этого достаточно для некоторых случаев.

Если вы хотите получить чистое решение, вам нужно изменить шаблон расширителя.

Другой способ - это прикрепленное свойство:

using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public static class ParentContentPresenter
{
    public static readonly System.Windows.DependencyProperty HorizontalAlignmentProperty = System.Windows.DependencyProperty.RegisterAttached(
        "HorizontalAlignment",
        typeof(HorizontalAlignment),
        typeof(ParentContentPresenter),
        new PropertyMetadata(default(HorizontalAlignment), OnHorizontalAlignmentChanged));

    public static void SetHorizontalAlignment(this UIElement element, HorizontalAlignment value)
    {
        element.SetValue(HorizontalAlignmentProperty, value);
    }

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static HorizontalAlignment GetHorizontalAlignment(this UIElement element)
    {
        return (HorizontalAlignment)element.GetValue(HorizontalAlignmentProperty);
    }

    private static void OnHorizontalAlignmentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var presenter = d.Parents().OfType<ContentPresenter>().FirstOrDefault();
        if (presenter != null)
        {
            presenter.HorizontalAlignment = (HorizontalAlignment) e.NewValue;
        }
    }

    private static IEnumerable<DependencyObject> Parents(this DependencyObject child)
    {
        var parent = VisualTreeHelper.GetParent(child);
        while (parent != null)
        {
            yield return parent;
            child = parent;
            parent = VisualTreeHelper.GetParent(child);
        }
    }
}

Это позволяет вам делать:

<Expander Header="{Binding ...}">
    <Expander.HeaderTemplate>
        <DataTemplate>
            <!--Using a border here to show how width changes-->
            <Border BorderBrush="Red" BorderThickness="1"
                    local:ParentContentPresenter.HorizontalAlignment="Stretch">
                ...    
            </Border>
        </DataTemplate>
    </Expander.HeaderTemplate>
</Expander>

Обратите внимание, что использование присоединенного свойства несколько хрупко, поскольку оно предполагает, что существует ContentPresenter в шаблоне.

Я очень удивлен, что никто не упомянул о том, чтобы просто отредактировать шаблон управления, все остальные решения имеют некоторые довольно серьезные недостатки, такие как неправильное вычисление ширины, не перерисовка, время рендеринга и т.д...

Этот шаблон управления изменит горизонтальное выравнивание заголовка contentpresenter в соответствии с фактическими расширителями (что означает, что он будет растягиваться).

    <ControlTemplate x:Key="ExpanderControlTemplate1" TargetType="{x:Type Expander}">
        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="True">
            <DockPanel>
                <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                    <ToggleButton.FocusVisualStyle>
                        <Style>
                            <Setter Property="Control.Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Border>
                                            <Rectangle Margin="0" SnapsToDevicePixels="True" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ToggleButton.FocusVisualStyle>
                    <ToggleButton.Style>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="19"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>
                                                <Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19"/>
                                                <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center"/>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ToggleButton.Style>
                </ToggleButton>
                <ContentPresenter x:Name="ExpandSite" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" DockPanel.Dock="Bottom" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </DockPanel>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsExpanded" Value="True">
                <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Right">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19"/>
                                                    <RowDefinition Height="*"/>
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="-90"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Up">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="19"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="180"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Left">
                <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
                <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
                <Setter Property="Style" TargetName="HeaderSite">
                    <Setter.Value>
                        <Style TargetType="{x:Type ToggleButton}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                                        <Border Padding="{TemplateBinding Padding}">
                                            <Grid Background="Transparent" SnapsToDevicePixels="False">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="19"/>
                                                    <RowDefinition Height="*"/>
                                                </Grid.RowDefinitions>
                                                <Grid>
                                                    <Grid.LayoutTransform>
                                                        <TransformGroup>
                                                            <RotateTransform Angle="90"/>
                                                        </TransformGroup>
                                                    </Grid.LayoutTransform>
                                                    <Ellipse x:Name="circle" Fill="White" HorizontalAlignment="Center" Height="19" Stroke="#FF333333" VerticalAlignment="Center" Width="19"/>
                                                    <Path x:Name="arrow" Data="M1,1.5L4.5,5 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="False" Stroke="#FF333333" StrokeThickness="2" VerticalAlignment="Center"/>
                                                </Grid>
                                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                            </Grid>
                                        </Border>
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsChecked" Value="True">
                                                <Setter Property="Data" TargetName="arrow" Value="M1,4.5L4.5,1 8,4.5"/>
                                            </Trigger>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF5593FF"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFF3F9FF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsPressed" Value="True">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FF3C77DD"/>
                                                <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFD9ECFF"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="Black"/>
                                            </Trigger>
                                            <Trigger Property="IsEnabled" Value="False">
                                                <Setter Property="Stroke" TargetName="circle" Value="#FFBCBCBC"/>
                                                <Setter Property="Fill" TargetName="circle" Value="#FFE6E6E6"/>
                                                <Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

Я согласен с HTH - проверьте, в какой контейнер вы помещаете Расширитель...StackPanel всегда будет сворачивать свои дочерние элементы до наименьшего размера, до которого они могут дойти.

Я часто использую расширители в своем проекте, и если вы поместите их в сетку / DockPanel, то расширитель заполнит все доступное пространство (при условии, что его вертикальная и горизонтальная ориентации установлены на растягивание).

Предложение Джонатана привязать ширину расширителя к ширине контейнера может оказаться немного запутанным...Я попробовал этот метод несколько недель назад и обнаружил, что в некоторых случаях он может привести к нежелательным результатам, поскольку может препятствовать функционированию системы компоновки.

PS:В качестве общего совета (и я уверен, что меня будут ругать за то, что я это написал), если вы не уверены в том, в каком макете-контейнере использовать ваши элементы управления, начните с сетки.Использование определений столбцов и строк позволяет вам очень легко контролировать, используют ли дочерние элементы управления минимальное пространство ("Auto"), максимальное пространство ("*") или точное количество пространства ("[number]").

<Expander Name="EXPANDER_NAME">
    <Expander IsExpanded="True" Margin="0">
        <Expander.Header>
            <Grid Background="Red" Width="{Binding ElementName=EXPANDER_NAME, Path=ActualWidth}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="30"/>
                </Grid.ColumnDefinitions>
                <TextBlock>          HEADER TEXT          <TextBlock>
            </Grid>
        </Expander.Header>
   </Expander>

Инструментарий Silverlight включает в себя Аккордеон элемент управления, который действует как расширитель, который всегда растягивается до доступного места.Я еще не тестировал его, но он может быть функционален и для WPF, как элементы управления Silverlight Chart.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top