如何在XAML中创建可重用控件并使用通用模板/控件设置嵌套控件的属性

3

我尝试通过谷歌搜索了解这个问题,但是我对人们提出的建议不是非常清楚。在一个用户控件中,我有三个按钮,它们除了自动化ID和文本之外完全相同。我不想在所有按钮上复制此代码,而是希望创建一个通用控件或控件模板来使用。我的问题是这些按钮有嵌套控件,我需要更改它们的文本,但我不确定如何做到这一点。

<UserControl>

<Grid>       
        <StackPanel x:Name="myStackPanel" Grid.Row="1" Padding="0">
            <Button AutomationProperties.AutomationId="CallButton" x:Name="CallButton" Style="{StaticResource ButtonStyle}">
                <RelativePanel>
                    <SymbolIcon AutomationProperties.AutomationId="CallIcon" x:Name="CallIcon" Symbol="Phone" Style="{StaticResource SymbolStyle}" />
                    <StackPanel>
                        <TextBlock AutomationProperties.AutomationId="CallLabel" Text="Call" Style="{StaticResource LabelStyle}"/>
                        <TextBlock AutomationProperties.AutomationId="CallText" Text="123-456-7890" Style="{StaticResource ContentStyle}"/>
                    </StackPanel>
                </RelativePanel>
            </Button>
            <Button AutomationProperties.AutomationId="EmailButton" x:Name="EmailButton" Style="{StaticResource ButtonStyle}">
                <RelativePanel>
                    <SymbolIcon AutomationProperties.AutomationId="EmailIcon" x:Name="EmailIcon" Symbol="Mail" Style="{StaticResource SymbolStyle}"/>
                    <StackPanel >
                        <TextBlock AutomationProperties.AutomationId="EmailLabel" Text="Email" Style="{StaticResource LabelStyle}"/>
                        <TextBlock AutomationProperties.AutomationId="EmailText" Text="meetme@email.com" Style="{StaticResource ContentStyle}"/>
                    </StackPanel>
                </RelativePanel>
            </Button>
            <Button AutomationProperties.AutomationId="WebsiteButton" x:Name="WebsiteButton" Style="{StaticResource ButtonStyle}">
                <RelativePanel>
                    <SymbolIcon AutomationProperties.AutomationId="WebsiteIcon" x:Name="WebsiteIcon" Symbol="Link" Style="{StaticResource SymbolStyle}"/>
                    <StackPanel >
                        <TextBlock AutomationProperties.AutomationId="WebsiteLabel" Text="Website" Style="{StaticResource LabelStyle}"/>
                        <TextBlock AutomationProperties.AutomationId="WebsiteText" Text="http://meetme.com" Style="{StaticResource ContentStyle}"/>
                    </StackPanel>
                </RelativePanel>
            </Button>
        </StackPanel>          
    </Grid>
</Grid>

正如您所见,所有3个按钮的代码都是相同的。我想做的就是创建一个控件,可以设置嵌套控件的自动化ID和文本属性。

谢谢!

2个回答

1

你可能需要做更多的工作,但听起来你想要创建一个UserControl。在代码后台,它应该从Button继承:

public partial class MyButton: Button

在XAML中,您将包含每个按钮现在具有的基本内容。

繁琐的部分是,然后(在代码后台)需要为您想要在此控件中设置的每个“属性”创建一个DependencyProperty:例如,一个用于CallIconAutomationId,一个用于CallLabelAutomationId,一个用于CallLabelText等。 然后,在XAML中将每个这些属性绑定到依赖项属性。 这些属性成为您将在每个单独的MyButton(您的新UserControl)上设置的数据。

然后,在托管这些控件的容器中(在您上面的示例中似乎是另一个UserControl),您将在每个新的MyButton控件上设置这些自定义属性,看起来像这样:

<myNamespace:MyButton EmailIconAutomationId="EmailIcon" LabelAutomationId="EmailLabel" />

基本上,您正在创建一个新控件(UserControl),该控件基于按钮控件(这为您提供了大部分功能),并直接向该新控件添加新的自定义属性(这些属性与您习惯使用的所有其他控件属性一样)。

等等。


谢谢!那解释得很清楚,我需要做什么。但是绑定似乎不正常。我设置了断点,看到属性被设置了,但在运行时没有显示任何文本。有什么想法吗?我会更新问题的。 - user1192724
是的,请显示绑定,它们应该非常简单。 - karfus

1
您可以基于一个 UserControl(添加一个新的 UserControl)来创建一个按钮。这将允许您享受所有默认按钮的属性、事件和状态(OnClick、Command等),并且添加自己的属性、模板和行为。
如果您希望在它们上面使用绑定或动画,则强烈建议使用依赖属性而不是简单属性。 C#:
public partial class CustomButton : Button
{

    #region IconAutomationId

    public string IconAutomationId
    {
        get { return (string)GetValue(IconAutomationIdProperty); }
        set { SetValue(IconAutomationIdProperty, value); }
    }

    public static readonly DependencyProperty IconAutomationIdProperty =
        DependencyProperty.Register("IconAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    #region LabelAutomationId

    public string LabelAutomationId
    {
        get { return (string)GetValue(LabelAutomationIdProperty); }
        set { SetValue(LabelAutomationIdProperty, value); }
    }

    public static readonly DependencyProperty LabelAutomationIdProperty =
        DependencyProperty.Register("LabelAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    #region TextAutomationId

    public string TextAutomationId
    {
        get { return (string)GetValue(TextAutomationIdProperty); }
        set { SetValue(TextAutomationIdProperty, value); }
    }

    public static readonly DependencyProperty TextAutomationIdProperty =
        DependencyProperty.Register("TextAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    #region Symbol

    public object Symbol
    {
        get { return (object)GetValue(SymbolProperty); }
        set { SetValue(SymbolProperty, value); }
    }

    public static readonly DependencyProperty SymbolProperty =
        DependencyProperty.Register("Symbol", typeof(object), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    #region Label

    public string Label
    {
        get { return (string)GetValue(LabelProperty); }
        set { SetValue(LabelProperty, value); }
    }

    public static readonly DependencyProperty LabelProperty =
        DependencyProperty.Register("Label", typeof(string), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    #region Text

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(CustomButton), new PropertyMetadata(null));

    #endregion

    public CustomButton()
    {
        InitializeComponent();
    }
}

XAML:

<Button x:Class="WpfApplication1.CustomButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="customButton">

    <RelativePanel>
        <SymbolIcon AutomationProperties.AutomationId="{Binding IconAutomationId, ElementName=customButton}"
                    Symbol="{Binding Symbol, ElementName=customButton}"
                    Style="{StaticResource SymbolStyle}"/>
        <StackPanel >
            <TextBlock AutomationProperties.AutomationId="{Binding LabelAutomationId, ElementName=customButton}"
                       Text="{Binding Label, ElementName=customButton}"
                       Style="{StaticResource LabelStyle}"/>
            <TextBlock AutomationProperties.AutomationId="{Binding TextAutomationId, ElementName=customButton}"
                       Text="{Binding Text, ElementName=customButton}"
                       Style="{StaticResource ContentStyle}"/>
        </StackPanel>
    </RelativePanel>
</Button>

用途:

<local:CustomButton AutomationProperties.AutomationId="CallButton"
                    x:Name="CallButton"
                    Style="{StaticResource ButtonStyle}"
                    IconAutomationId="CallIcon"
                    LabelAutomationId="CallLabel"
                    TextAutomationId="CallText"
                    Symbol="Phone"
                    Label="Call"
                    Text="123-456-7890"/>

我漏掉了ElementName部分。感谢你和Karfus! - user1192724

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接