Заменить часть шаблона по умолчанию в WPF

есть ли способ "лучшей практики" заменить часть шаблона по умолчанию. Текущий вариант использования - древовидная структура. По умолчанию древовидная структура имеет такие маленькие треугольные фигуры, которые расширяются и сжимаются.

Я знаю, как их заменить, если я заменю весь шаблон управления, как показано в приведенном ниже коде. Я не уверен, есть ли способ "сохранить все умолчания, просто измените XY". Это не стиль, мне в основном нужно заменить часть существующего шаблона управления.

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

Большая вторая и третья части - это в основном копия шаблонов по умолчанию, только для администрирования "измененной" части с самого начала.

Есть ли лучший способ сделать это, сохраняя длинный и запутывающий XAML во второй половине?

<resourcedictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
</resourcedictionary>

                                                          

<setter property="Template">
 <setter.value>
 <controltemplate targettype="{x:Type TreeViewItem}">
 <grid>
 <grid.columndefinitions>
 <columndefinition minwidth="19" width="Auto">
 <columndefinition width="Auto">
 <columndefinition width="*">
 </columndefinition></columndefinition></columndefinition></grid.columndefinitions>
 <grid.rowdefinitions>
 <rowdefinition height="Auto">
 <rowdefinition>
 </rowdefinition></rowdefinition></grid.rowdefinitions>
 <togglebutton x:name="Expander" style="{StaticResource ExpandCollapseToggleStyle}" ischecked="{Binding Path=IsExpanded,
 RelativeSource={RelativeSource TemplatedParent}}" clickmode="Press">
 <border name="Bd" grid.column="1" background="{TemplateBinding Background}" borderbrush="{TemplateBinding BorderBrush}" borderthickness="{TemplateBinding BorderThickness}" padding="{TemplateBinding Padding}">
 <contentpresenter x:name="PART_Header" contentsource="Header" horizontalalignment="{TemplateBinding HorizontalContentAlignment}">
 </contentpresenter></border>
 <itemspresenter x:name="ItemsHost" grid.row="1" grid.column="1" grid.columnspan="2">
 </itemspresenter></togglebutton></grid>
 <controltemplate.triggers>
 <trigger property="IsExpanded" value="false">
 <setter targetname="ItemsHost" property="Visibility" value="Collapsed">
 </setter></trigger>
 <trigger property="HasItems" value="false">
 <setter targetname="Expander" property="Visibility" value="Hidden">
 </setter></trigger>
 <multitrigger>
 <multitrigger.conditions>
 <condition property="HasHeader" value="false">
 <condition property="Width" value="Auto">
 </condition></condition></multitrigger.conditions>
 <setter targetname="PART_Header" property="MinWidth" value="75">
 </setter></multitrigger>
 <multitrigger>
 <multitrigger.conditions>
 <condition property="HasHeader" value="false">
 <condition property="Height" value="Auto">
 </condition></condition></multitrigger.conditions>
 <setter targetname="PART_Header" property="MinHeight" value="19">
 </setter></multitrigger>
 <trigger property="IsSelected" value="true">
 <setter targetname="Bd" property="Background" value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
 <setter property="Foreground" value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}">
 </setter></setter></trigger>
 <multitrigger>
 <multitrigger.conditions>
 <condition property="IsSelected" value="true">
 <condition property="IsSelectionActive" value="false">
 </condition></condition></multitrigger.conditions>
 <setter targetname="Bd" property="Background" value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
 <setter property="Foreground" value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}">
 </setter></setter></multitrigger>
 <trigger property="IsEnabled" value="false">
 <setter property="Foreground" value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}">
 </setter></trigger>
 </controltemplate.triggers>
 </controltemplate>
 </setter.value>
</setter>
3 ответа

К сожалению, я думаю, вам нужно заменить весь шаблон:

Из MSDN: http://msdn.microsoft.com/en-us/library/aa970773.aspx

Элементы управления в представлении Windows Фонд (WPF) имеет ControlTemplate, который содержит визуальное дерево этого контроля. Ты можешь изменить структуру и внешний вид контроль путем изменения ControlTemplate этого элемента управления. Там не может заменить только часть визуальное дерево элемента управления; изменить визуальное дерево элемента управления, которое вы должны установите свойство Template контроль за его новым и полным ControlTemplate.


На самом деле есть способ (вроде). Вы можете создать свой собственный элемент управления и переопределить функцию OnApplyTemplate, чтобы динамически изменять стиль.

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

namespace SilverlightClassLibrary1
{
 public class MyButton: Button
 {
 public string BackgroundColor { get; set; }
 public override void OnApplyTemplate()
 {
 base.OnApplyTemplate();
 if (BackgroundColor != null)
 {
 Rectangle r = this.GetTemplateChild("BackgroundGradient") as Rectangle;
 if (r != null)
 {
 r.Fill = new SolidColorBrush(Color.FromArgb(255, 
 Convert.ToByte(BackgroundColor.Substring(1,2),16),
 Convert.ToByte(BackgroundColor.Substring(3,2),16),
 Convert.ToByte(BackgroundColor.Substring(5,2),16)));
 }
 }
 }
 }
}

Интересной частью является метод GetTemplateChild, который ищет элемент управления Rectangle с именем "BackgroundGradient". (BTW, проще, если вы определяете настраиваемые элементы управления в отдельном проекте, поэтому создайте новый проект библиотеки Silverlight, если вы еще этого не сделали и не поместили его в этот проект.)

Затем добавьте новый файл словаря ресурсов и переопределите шаблон управления и убедитесь, что у вас есть прямоугольник с именем "BackgroundGradient". В этом случае мы используем стандартный шаблон управления кнопками, который я немного сократил:

<resourcedictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:custom="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1">
 
</resourcedictionary>

Итак, теперь вы можете объявить элемент управления кнопкой и переопределить стиль, если хотите:

<usercontrol x:class="SilverlightApplication1.MainPage" ...="" xmlns:custom="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1">
 <custom:mybutton>Normal Button 1</custom:mybutton>
 <custom:mybutton>Normal Button 2</custom:mybutton>
 <custom:mybutton backgroundcolor="#8888cc">Customized Background</custom:mybutton>
</usercontrol>

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

Затем вам необходимо включить свой файл ресурсов как часть вашего приложения:

<application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:class="SilverlightApplication1.App">
 <application.resources>
 <resourcedictionary>
 <resourcedictionary.mergeddictionaries>
 <resourcedictionary source="Dictionary1.xaml">
 </resourcedictionary></resourcedictionary.mergeddictionaries>
 </resourcedictionary>
 </application.resources>
</application>

и вы увидите изменения пользовательского свойства в своем дизайне XAML.


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

Чтобы использовать эти заполнители, вы должны связать их с зависимыми свойствами.

Отметьте это сообщение, чтобы узнать, как это делается.

http://www.codeproject.com/Articles/82464/How-to-Embed-Arbitrary-Content-in-a-WPF-Control

"Использование пользовательского контроля" объясняет мой подход

licensed under cc by-sa 3.0 with attribution.