WPF ContentPresenter переопределяет другие элементы управления на том же уровне.

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

Шаблон расширителя:

<ControlTemplate TargetType="Expander">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="15"/>
        </Grid.RowDefinitions>
        <ContentPresenter x:Name="ContentPresenter" Grid.Row="0"/>
        <ToggleButton Grid.Row="1" >
           ....
        </ToggleButton>
    </Grid>

Теперь, когда я использую этот пользовательский элемент управления в своем основном представлении и добавляю элемент управления (например, кнопку):

<custom:FullWidthExpander Width="200" HeaderBackground="Gray">
    <Button />
</custom:FullWidthExpander>

ToggleButton (который определен в моем шаблоне Expander выше) переопределяется этой кнопкой.


person Th1sD0t    schedule 21.01.2016    source источник
comment
Вы уверены, что это переопределено, а не просто скрыто кнопкой? вы можете использовать Snoop, чтобы посмотреть, как именно выглядит ваш элемент управления при загрузке и работе.   -  person KinSlayerUY    schedule 21.01.2016
comment
да, при отслеживании моего приложения все, кроме ContentPresenter, отсутствует :/   -  person Th1sD0t    schedule 21.01.2016
comment
Если вы добавите размер к своей кнопке, это все еще произойдет? Кнопка занимает весь доступный размер, поэтому Auto, вероятно, будет вашим размером Expander.   -  person nkoniishvt    schedule 21.01.2016
comment
Где находится ваш ControlTemplate? И могу ли я с уверенностью предположить, что FullWidthExpander является пользовательским UserControl? Я сделал быстрый тест с обычным расширителем только в XAML в MainWindow, и он работает отлично, поэтому я предполагаю, что ваша проблема как-то связана с вашей иерархией управления.   -  person Rachel    schedule 21.01.2016


Ответы (2)


Вы привязываете свойство UserControl.Content к свойству Expander.Content?

<!-- define a custom Template for the UserControl FullWidthExpander -->
<UserControl.Template>
    <ControlTemplate TargetType="UserControl">
        <!-- be sure to include the Content binding to pass the UC.Content to Expander -->
        <Expander Content="{TemplateBinding Content}">
            <!-- create a custom Template for this Expander -->
            <Expander.Template>
                <ControlTemplate TargetType="Expander">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition x:Name="ContentRow" Height="*"/>
                            <RowDefinition Height="20"/>
                        </Grid.RowDefinitions>
                        <ContentPresenter Grid.Row="0" Content="{TemplateBinding Content}"/>
                        <ToggleButton Grid.Row="1" Content="Test Toggle Button" />
                    </Grid>
                </ControlTemplate>
            </Expander.Template>
        </Expander>
    </ControlTemplate>
</UserControl.Template>

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

<local:FullWidthExpander>
    <Button Content="Test Content Button"/>
</local:FullWidthExpander>

введите здесь описание изображения

Я также просмотрел ваш другой вопрос, и если у вас есть ControlTemplate.Triggers здесь, вы также захотите убедиться, что установите Expander.IsExpanded на True для просмотра вашего Контента. Ваш триггер скрывает верхнюю строку содержимого, если IsExpanded=False, что является значением по умолчанию для Expander.

person Rachel    schedule 21.01.2016
comment
Спасибо за ваш ответ :) - Если я правильно понял, это решение - просто грязный обходной путь. Чтобы уточнить, я просто хотел сделать многоразовый расширитель с новым внешним видом. Вы можете сказать мне, что было бы оптимальным решением? (Я не хочу оскорблять вас, говоря, что это обходной путь, но, насколько я понял, пользовательский контроль не лучший вариант для моей цели) - person Th1sD0t; 22.01.2016
comment
@Chill-X В вашем случае, да, вероятно, лучше просто использовать собственный шаблон для вашего расширителя, чем совершенно новый пользовательский элемент управления, однако основная проблема будет такой же, несмотря ни на что. Хорошо знать причину и решение, чтобы не сталкиваться с такими проблемами в будущем :) - person Rachel; 22.01.2016

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

<custom:FullWidthExpander Width="200" HeaderBackground="Gray">
    <Button />
</custom:FullWidthExpander>

Чтобы обойти это, вам нужно немного по-другому разместить контент в своем пользовательском контроле.

Сначала добавьте свойство зависимости для пользовательского элемента управления.

    public object UserControlContent
    {
        get { return (object)GetValue(UserControlContentProperty); }
        set { SetValue(UserControlContentProperty, value); }
    }

    public static readonly DependencyProperty UserControlContentProperty =
        DependencyProperty.Register("UserControlContent", typeof(object), typeof(FullWidthExpander),
          new PropertyMetadata(null));

Затем привяжите это к презентатору содержимого в xaml пользовательского элемента управления, а также определите имя для своего пользовательского элемента управления, например x: Name = "Root".

<Expander Header="My expander header">
    <Expander.Template>
        <ControlTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="15"/>
                </Grid.RowDefinitions>

                <ContentPresenter x:Name="ContentPresenter" Grid.Row="0" Content="{Binding UserControlContent, ElementName=Root}" />

                <ToggleButton Grid.Row="1" Content="Togglebutton">

                </ToggleButton>
            </Grid>
        </ControlTemplate>
    </Expander.Template>
</Expander>

И, наконец, вы определяете содержимое содержимого в maindwindow xaml как таковое.

<custom:FullWidthExpander>
    <custom:FullWidthExpander.UserControlContent>
        <Button Content="Click me"/>
    </custom:FullWidthExpander.UserControlContent>
</custom:FullWidthExpander>
person Janne Matikainen    schedule 21.01.2016
comment
Спасибо за ваш ответ, но я думал, что ContentPresenter является своего рода заполнителем для контента, который я предоставляю? - person Th1sD0t; 21.01.2016
comment
Для шаблонов да, для пользовательских элементов управления нет. - person Janne Matikainen; 21.01.2016
comment
@JanneMatikainen, он ничего не говорил о UserControl - person nkoniishvt; 21.01.2016
comment
@nkoniishvt это моя вина - Expander, конечно, является UserControl. (Думал, что это очевидно, потому что я сказал, что собираюсь создать новый Expander). Итак, если я определю дизайн своего расширителя внутри основного представления как стиль/шаблон с ContentPresenter, как указано выше, он будет работать? - person Th1sD0t; 21.01.2016
comment
@Chill-X Я не понимаю, зачем вам нужен ControlTemplate для UserControl, если вы можете напрямую определить, как он должен отображаться в .xaml UserControl. ControlTemplate (обычно) используются для CustomControl, а не для UserControl - person nkoniishvt; 21.01.2016
comment
@nkoniishvt Я все еще довольно новичок в программировании WPF, и, как уже упоминалось, я буду делать странные вещи, потому что сейчас учусь :) Основная причина, по которой я хочу использовать шаблоны внутри UserControl, заключалась в том, что я хотел создать повторно используемый элемент управления (например, , расширитель). - person Th1sD0t; 21.01.2016
comment
@Chill-X вам не нужен шаблон, чтобы сделать элемент управления многоразовым, вам нужны только DependencyProperties. Пользовательский элемент управления следует использовать, когда вы определяете новый элемент управления, который ведет себя не так, как другие элементы управления, и не является композицией элементов управления. Дополнительная информация в этом ответе: stackoverflow.com/a/11248415/4049478 - person nkoniishvt; 21.01.2016
comment
Лично я использую пользовательский элемент управления, когда мне нужно только составить несколько (уже стилизованных/шаблонных) элементов управления в одну логическую единицу, где внешний вид различных элементов управления не зависит от других элементов управления. В случае пользовательского расширителя это не так, поэтому я бы разработал пользовательский элемент управления, а пользовательский элемент управления имеет свой собственный шаблон управления. Для пользовательских элементов управления вы не устанавливаете шаблон управления (хотя это возможно, поскольку пользовательский элемент управления является производным от элемента управления контентом). - person Rob van Daal; 21.01.2016
comment
Итак, UserControl используется для создания нового элемента управления из существующих. Как упоминалось ниже, я просто хотел создать многоразовый расширитель с новым внешним видом — какое решение было бы лучшим для этого? Шаблон в моем MainView? Но это не будет многоразовым, не так ли? - person Th1sD0t; 22.01.2016
comment
Вы можете определить шаблон в ресурсах приложения. Если вам каким-то образом нужно привязать заголовок и содержимое к чему-то другому, вам нужно использовать элемент управления с зависимостями, которые вы можете привязать в макете, как в моем примере. - person Janne Matikainen; 22.01.2016