WPF 创建可用于扩展另一个 UserControl 的基 UserControl

WPF Creating a base UserControl that can be used to extend another UserControl

提问人:처NecixsFX 提问时间:10/10/2023 更新时间:10/13/2023 访问量:83

问:

我是 WPF 的新手,我想创建一个可重用的基本 UserControl。

例如,我有这个UserControl:TestBase

<UserControl x:Class="UserControls.TestBase"
             xmlns=""
             xmlns:x=""
             xmlns:mc="" 
             xmlns:d="" 
             xmlns:local="clr-namespace:UserControls"
             mc:Ignorable="d" 
             Style="{StaticResource TestBaseDefault}"
             d:DesignHeight="150" d:DesignWidth="150">
    <UserControl.Template>
        <ControlTemplate>
            <Grid>
                <TextBlock Text="Base Text" 
                           HorizontalAlignment="Center" VerticalAlignment="Center"
                           Foreground="White"/>
            </Grid>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

UserControl TestBase 使用此样式 (TestBaseDefault):

<Style x:Key="TestBaseDefault" TargetType="{x:Type UserControl}">
    <Setter Property="Margin" Value="5"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type UserControl}">
                <Border CornerRadius="10" BorderThickness="2" BorderBrush="{StaticResource ForegroundBrush}" Background="{StaticResource BackgroundBrush}" Padding="10">
                    <ContentPresenter/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在,我想创建第二个从 TestBase 扩展的 UserControl。

目前看起来像这样:Test1

<UserControl x:Class="UserControls.Test1"
                xmlns=""
                xmlns:x=""
                xmlns:mc="" 
                xmlns:d="" 
                xmlns:local="clr-namespace:UserControls"
                x:Name="self"
                mc:Ignorable="d" 
                d:DesignHeight="150" d:DesignWidth="150">
    <Grid>

        <TextBlock Text="Overriden Text" 
                   HorizontalAlignment="Center" VerticalAlignment="Center"
                   Foreground="White"/>
    </Grid>
</UserControl>

必须从UserControls中删除链接,否则我无法发布问题。

我想知道的是,是否可以从 TestBase 而不是 UserControl 扩展 Test1,以便我可以从基访问属性、使用其中的 Style 并覆盖默认内容?

如果没有,有没有其他方法可以实现?

C# WPF XAML 用户控件

评论

0赞 JonasH 10/10/2023
我建议使用组合而不是继承来重用 wpf 控件。可以创建一个公开依赖项属性的控件,包括放在控件内某个位置的“内容”等内容。

答:

0赞 mm8 10/11/2023 #1

基类应定义为没有任何 XAML 的类:

public class TestBase : UserControl
{
    public TestBase()
    {
        Style = FindResource("TestBaseDefault") as Style;
    }
}

然后,您可以将其用作 的基类。Test1

Test1.xaml:

<local:TestBase x:Class="WpfApp1.Test1"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>

        <TextBlock Text="Overriden Text" 
                   HorizontalAlignment="Center" VerticalAlignment="Center"
                   Foreground="White"/>
    </Grid>
</local:TestBase>

Test1.xaml.cs:

public partial class Test1 : TestBase
{
    public Test1()
    {
        InitializeComponent();
    }
}

您无法覆盖模板,因此应删除已定义的模板或将其合并到样式定义的模板中。TestBase.xaml

评论

0赞 처NecixsFX 10/12/2023
这对我有用,很棒的解决方案。谢谢!
1赞 Ferid Š. Sejdović 10/11/2023 #2

由于所有内容都与问题中的样式有关(与该确切的控件相关),因此您应该定义基本控件的默认样式并设置文本属性(无论您想要什么)。不需要创建 c# 基控件类,除非由于某些要求而明确需要它。

如果要使用或覆盖基本控件的样式,只需在定义它时使用以下命令:

BasedOn=TestBaseDefault

因此,基本样式是:

<Style x:Key="TestBaseDefault" TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="5"/>
    <Setter Property="VerticalAlignment" 
Value="Top"/>
        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type UserControl}">
                <Border CornerRadius="10" BorderThickness="2" BorderBrush="{StaticResource ForegroundBrush}" Background="{StaticResource BackgroundBrush}" Padding="10">
                    <ContentPresenter/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

对于第二个控件,请使用以下命令:

<Style x:Key="OtherControlStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TestBaseDefault}" >
        <Setter Property="Margin" Value="10"/>
       
    </Style>

它将使用默认样式和新的覆盖值。

最后,将样式设置为控件:

    <TextBox Text="Base Text"                           HorizontalAlignment="Center" VerticalAlignment="Center"                          Foreground="White" 
Style="{StaticResource TestBaseDefault}"/>

第二个和所有其他的......

<TextBox Text="Overriden Text"                     HorizontalAlignment="Center"     VerticalAlignment="Center"
Foreground="White"
Style="{StaticResource     OtherControlStyle}"/>

ps:HorizontalAlignment、VerticalAligment、Foreground 应该在样式中定义,而不是直接在控件上定义,但当然也允许覆盖某些属性,但没有必要在两个位置为同一个控件设置两个值。 并确保你很好地引用了它们......