изменить свойство ContentPresenter HorisontalAlign заголовка Expander

Я хочу иметь собственный заголовок в элементе управления Expander. Я хочу иметь текст заголовка с выравниванием по левому краю и изображение с выравниванием по правому краю:

<Expander>
    <Expander.Header>
        <DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
            <TextBlock DockPanel.Dock="Left" Text="Some Header Text"/>
            <Image DockPanel.Dock="Right" HorizontalAlignment="Right"  />
         </DockPanel>
     </Expander.Header>
     <StackPanel >
         <ItemsPresenter />
     </StackPanel>
</Expander>

К сожалению, заголовок отображается внутри элемента, который по умолчанию не растягивается по горизонтали. Этот элемент представляет собой элемент управления ContentPresenter, и по умолчанию он не растягивается, поскольку его значение HorisontalAlign равно Left. Если я изменю его на Stretch (я сделал это в инструменте Snoop), то заголовок будет отображаться так, как я этого хочу. Но как мне изменить это из кода?

Я попытался добавить стиль ContentPresenter к ресурсам Expander с правильным значением HorizontalAlignment, но, к сожалению, это не сработало. Вероятно, к ContentPresenter применен какой-то пользовательский стиль, и поэтому он не ухватился за мой стиль. Я пробовал это так:

<Expander.Resources>
    <Converters:TodoTypeToHeaderTextConverter x:Key="TodoTypeToHeaderTextConverter" />
    <Style TargetType="ContentPresenter">
        <Setter Property="HorizontalAlignment" Value="Stretch" />
    </Style>
</Expander.Resources>

Так что еще я могу попробовать?


person Bogdan Verbenets    schedule 19.07.2012    source источник


Ответы (2)


Попробуйте что-то вроде этого:

XAML-файл:

<Expander Name="exp" Header="test" Loaded="exp_Loaded">
            <Expander.HeaderTemplate>
                <DataTemplate>
                    <DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
                        <TextBlock DockPanel.Dock="Left" Text="{Binding}"/>
                        <Image Source="/ExpanderStyle;component/animation.png" Width="20"
                               DockPanel.Dock="Right" HorizontalAlignment="Right" />
                    </DockPanel>
                </DataTemplate>
            </Expander.HeaderTemplate>                
        </Expander>

Код программной части:

private void exp_Loaded(object sender, RoutedEventArgs e)
        {
            var tmp = VTHelper.FindChild<ContentPresenter>(sender as Expander);
            if (tmp != null)
            {
                tmp.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            }
        }

И вспомогательный класс:

public static class VTHelper
    {
        public static T FindChild<T>(DependencyObject parent) where T : DependencyObject
        {
            if (parent == null) return null;

            T childElement = null; 
            int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                T childType = child as T; 
                if (childType == null)
                {
                    childElement = FindChild<T>(child); 
                    if (childElement != null) 
                        break;
                }
                else
                {
                    childElement = (T)child; 
                    break;
                }
            } 
            return childElement;
        }
    }
person kmatyaszek    schedule 19.07.2012
comment
Этот код выглядит таким многообещающим, но FindChild просто возвращает null для меня. И это несмотря на то, что я могу видеть ContentPresenter в визуальном дереве с помощью инспектора Visual Studio. - person Christian Findlay; 30.04.2018
comment
VisualTreeHelper.GetChildrenCount(expander) возвращает для меня 0. - person Christian Findlay; 30.04.2018

Другой способ исправить это — отредактировать шаблоны: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/28a0f2d2-70cc-4935-9613-790ec0c8895a .

person Bogdan Verbenets    schedule 20.07.2012