XAML WinUI 3 -带内容的自定义控件

46qrfjad  于 2023-09-28  发布在  其他
关注(0)|答案(3)|浏览(181)

我找不到如何轻松地创建一个自定义控件,我可以在其中插入xaml的内容。例如,我希望控件包含一个网格,我以某种方式设置了该网格的样式,然后从组件外部向其中插入内容。

<local:MyComponent>
   ... some xaml content
</local:MyComponent>

我的想法是,有某种占位符告诉在哪里放置的内容。但它可能会有所不同。

<UserControl>
    <Grid>
        <ContentPlaceholder />
    </Grid>
</UserControl>
yvgpqqbh

yvgpqqbh1#

现在有这样的控制。它被称为ContentControl。它有一个Content属性,可以设置为任何XAML内容。然后,您可以使用Template属性来定义ControlTemplate及其周围的Grid,例如:

<ContentControl>
    <ContentControl.Template>
        <ControlTemplate TargetType="ContentControl">
            <Grid Background="Yellow">
                <ContentPresenter />
            </Grid>
        </ControlTemplate>
    </ContentControl.Template>
    <ContentControl.Content>
        <!-- Some XAML content: -->
        <TextBlock>some content...</TextBlock>
    </ContentControl.Content>
</ContentControl>

为了能够重用ContentTemplate,可以将其作为资源存储在资源字典中。例如App.xaml

<?xml version="1.0" encoding="utf-8"?>
<Application
    x:Class="App1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!-- Other merged dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <ControlTemplate x:Key="gridTemplate" TargetType="ContentControl">
                <Grid Background="Yellow">
                    <ContentPresenter />
                </Grid>
            </ControlTemplate>
        </ResourceDictionary>
    </Application.Resources>
</Application>

用法:

<ContentControl Template="{StaticResource gridTemplate}">
    <!-- Some XAML content: -->
    <TextBlock>some content...</TextBlock>
</ContentControl>

您还可以将Content属性设置为任何对象,并使用ContentTemplate属性定义此对象的外观。

ddrv8njm

ddrv8njm2#

让我给你们看两个例子:

实施例A

创建一个自定义控件并为您的内容添加一个DependencyProperty。您还需要添加ContentProperty属性,以便可以在XAML中设置内容。
CustomControl.cs

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;

namespace CustomContentControlExample;

[ContentProperty(Name = "Content")]
public sealed class CustomControl : Control
{
    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.Register(
            nameof(Content),
            typeof(object),
            typeof(CustomControl),
            new PropertyMetadata(default));

    public CustomControl()
    {
        this.DefaultStyleKey = typeof(CustomControl);
    }

    public object Content
    {
        get => GetValue(ContentProperty);
        set => SetValue(ContentProperty, value);
    }
}

Generic.xaml

<Style TargetType="local:CustomControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomControl">
                <ContentPresenter Content="{TemplateBinding Content}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

实施例B

创建从ContentControl继承的自定义控件。
CustomContentControl.cs

using Microsoft.UI.Xaml.Controls;

namespace CustomContentControlExample;

public sealed class CustomContentControl : ContentControl
{
    public CustomContentControl()
    {
        this.DefaultStyleKey = typeof(CustomContentControl);
    }
}

Generic.xaml

<Style TargetType="local:CustomContentControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomContentControl">
                <ContentPresenter Content="{TemplateBinding Content}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

更新

如果你不想让Style在 * Generic.xaml * 中,你可以创建一个ResourceDictionary文件:
CustomContentControl.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CustomContentControlExample">

    <Style TargetType="local:CustomControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:CustomControl">
                    <ContentPresenter Content="{TemplateBinding Content}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

并在 Generic.xamlApp.xaml 中添加ResourceDictionary

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="CustomControl.xaml" />
</ResourceDictionary.MergedDictionaries>
x3naxklr

x3naxklr3#

谢谢大家提供的解决方案。他们都帮助我找到了我需要的解决方案。
我最终创建了一个单独的内容组件,如下所示:
1.我在Visula Studio中添加了一个新的UserControl(创建了MyContentControl.xaml文件+ MyContentControl.xaml.cs)
1.在文件MyContentControl.xaml.cs中,我将继承从UserControl更改为ContentControl。3.在MyContentControl.xaml文件中,我将UserControl标记更改为ContentControl,并添加ContentControl.Template标记。
MyContentControl.xaml.cs

using Microsoft.UI.Xaml.Controls;

namespace winui_3_app.components;

public sealed partial class MyContentControl : ContentControl
{
    public MyContentControl()
    {
        this.InitializeComponent();
    }
}

MyContentControl.xaml

<ContentControl
    x:Class="winui_3_app.components.MyContentControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:winui_3_app.components"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <ContentControl.Template>
        <ControlTemplate TargetType="ContentControl">
            // Content decoration
            <Grid Background="Yellow" Padding="10, 10, 10, 10">
                <ContentPresenter />
            </Grid>
        </ControlTemplate>
    </ContentControl.Template>
    // Content placeholder
    <ContentControl.Content />
</ContentControl>

使用组件

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="winui_3_app.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="using:winui_3_app.components"
    mc:Ignorable="d">

    <Grid>
        <local:MyContentControl>
            // Some content
            <TextBlock>Hello!</TextBlock>
        </local:MyContentControl>
    </Grid>
</Window>

相关问题