0

我正在尝试实现一个控件以从 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>

在代码隐藏中,Button 用于 Click 事件以及标题文本,我想从继承自此的控件中填充该文本。

并且通过一个函数,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>

我想要实现的是在内部及其功能中重用带有 Button 和 TreeView 的 Stackpanel。

我尝试了两件事:

首先,我尝试创建一个模板并将其应用于基类。之后,我只是尝试使用 FindName<>() 函数在基类中加载模板的控件。

这里的问题是,模板是在 InitializeComponent() 之后应用的。
但是在 InitializeComponent() 期间,我已经需要访问权限,以便为从基类继承的控件设置标题的控件标题属性。

之后我尝试在控件的基类中完全实现子控件。
只需在构造函数中创建它们并将它们添加到基类继承的堆栈面板的 Children 属性中。

那确实(在某种程度上)起作用了。
但显然,当这样创建时,控件的行为完全不同。
无论设置如何。我只是无法让控件正确地适合他们的父母。
此外,在主题调整方面,这种方法完全不适合大型项目。

有人可以在这里指导我正确的方向吗?

4

1 回答 1

1

创建一个名为NavigatorItem(没有任何.xaml文件)的类:

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

创建一个ResourceDictionary被调用generic.xaml并将其放在themes项目根目录下的一个名为(这些名称是约定俗成的)文件夹中,并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!");
}
于 2020-02-26T13:30:22.353 回答