WPF Child Control Наследование - PullRequest
       13

WPF Child Control Наследование

0 голосов
/ 26 февраля 2020

Я пытаюсь реализовать элемент управления для наследования в WPF.

Я никогда не работал с WPF (хотя бы на этом уровне).
Поэтому мне нужно несколько рекомендаций по как решить эту проблему.

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

Допустим, у меня есть этот элемент управления.

<StackPanel x:Class="Framework.UI.Controls.Base.Navigator.NavigatorItem"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Framework.UI.Controls.Base.Navigator"
             mc:Ignorable="d" 
             d:DesignHeight="26" d:DesignWidth="200">
    <Button Name="btnHeader" Content="Button"/>
    <TreeView Name="tvNavContent" Height="0"/>
</StackPanel>

В codebehind кнопка используется для события Click, а также заголовок Text, который я хочу заполнить из элемента управления, который наследует отсюда.

И с помощью функции TreeView "tvNavContent" заполняется что-то вроде этого:

<TreeViewItem x:Class="Framework.UI.Controls.Base.Navigator.NavigatorEntry"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Framework.UI.Controls.Base.Navigator"
             mc:Ignorable="d" 
             d:DesignHeight="20" d:DesignWidth="200">
    <TreeViewItem.Header>
        <StackPanel Orientation="Horizontal">
            <Image Name="imgIcon" Width="16" Height="16" Stretch="Fill"/>
            <TextBlock Name="txtTitle"/>
        </StackPanel>
    </TreeViewItem.Header>
</TreeViewItem>

Чего я хочу добиться, так это повторно использовать Stackpanel w Внутри Button и TreeView и с его функциями.

Я попробовал две вещи:

Сначала я попытался создать шаблон и применил его к базовому классу. После этого я просто попытался загрузить элементы управления шаблона в базовом классе с помощью функции FindName <> ().

Проблема в том, что шаблон применяется после InitializeComponent ().
Но во время InitializeComponent () мне уже нужен доступ, чтобы установить свойство заголовка элемента управления для заголовка из элемента управления, который наследуется от базового класса.

После этого я попытался полностью реализовать дочерние элементы управления в базовом классе control.
Просто создал их в конструкторе и добавил их в Свойство Children панели стеков, от которого наследует базовый класс.

Это сработало (отчасти).
Но, видимо, элементы управления ведут себя совершенно иначе при создании так.
Независимо от настроек. Я просто не мог заставить элементы управления правильно вписаться в их родителей.
Кроме того, этот метод совершенно не подходит для более крупного проекта, когда речь идет о корректировке темы.

Может ли кто-нибудь помочь мне в правильном направление здесь?

1 Ответ

1 голос
/ 26 февраля 2020

Создайте класс с именем NavigatorItem (без файла .xaml):

public class NavigatorItem : Control
{
    static NavigatorItem()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NavigatorItem),
            new FrameworkPropertyMetadata(typeof(NavigatorItem)));
    }
}

Создайте ResourceDictionary с именем generic.xaml и поместите его в папку с именем themes (эти имена по соглашению) на root вашего проекта и определите там шаблон по умолчанию для класса NavigatorItem:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp12">
    <Style TargetType="local:NavigatorItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:NavigatorItem">
                    <StackPanel>
                        <Button Name="btnHeader" Content="Button"/>
                        <TreeView Name="tvNavContent" Height="0"/>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Затем вы можете переопределить OnApplyTemplate класса NavigatorItem получить ссылку на элементы в шаблоне и подключить к ним обработчики событий, например:

public override void OnApplyTemplate()
{
    Button button = GetTemplateChild("btnHeader") as Button;
    button.Click += Button_Click;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("button clicked!");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...