简体   繁体   English

如何将 ContentDialog 包装在自定义控件中?

[英]How do I wrap a ContentDialog in a custom Control?

I'm trying to make a re-usable WinUI dialog to display progress information, but I want the fact that I'm using a ContentDialog to be an implementation detail and not expose its API.我正在尝试制作一个可重复使用的 WinUI 对话框来显示进度信息,但我希望我使用ContentDialog作为实现细节,而不是公开其 API。 I figured I could do this by deriving from Control and creating a ContentDialog inside of its ControlTemplate .我想我可以通过从Control派生并在其ControlTemplate中创建一个ContentDialog来做到这一点。

Something like this:像这样的东西:

[TemplatePart(Name = PART_Dialog, Type = typeof(ContentDialog))]
public class ProgressDialog : Control
{
    private const string PART_Dialog = "PART_Dialog";

    private ContentDialog _dialog;

    public ProgressDialog()
    {
        DefaultStyleKey = typeof(ProgressDialog);
    }

    public async Task ShowAsync()
    {
        if (_dialog != null)
        {
            _ = await _dialog.ShowAsync(ContentDialogPlacement.Popup);
        }
    }

    protected override void OnApplyTemplate()
    {
        _dialog = GetTemplateChild(PART_Dialog) as ContentDialog;
        base.OnApplyTemplate();
    }
}

With a style defined like so:使用如下定义的样式:

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

    <Style TargetType="local:ProgressDialog" BasedOn="{StaticResource DefaultProgressDialog}" />

    <Style x:Key="DefaultProgressDialog" TargetType="local:ProgressDialog">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ProgressDialog">
                    <ContentDialog x:Name="PART_Dialog">
                        <Grid>
                            <TextBlock Text="Hello, world!" />
                        </Grid>
                    </ContentDialog>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

And then I would show the dialog like a ContentDialog :然后我会像ContentDialog一样显示对话框:

var dialog = new ProgressDialog();
dialog.XamlRoot = this.XamlRoot;
await dialog.ShowAsync();

I have the resource dictionary specified in Generic.xaml, but the control doesn't even attempt to load the template.我有 Generic.xaml 中指定的资源字典,但控件甚至没有尝试加载模板。 My OnApplyTemplate method is never called, so _dialog doesn't get wired up.我的OnApplyTemplate方法永远不会被调用,所以_dialog不会被连接起来。 I assume this is because I'm not actually creating the control in the visual tree, but then how does ContentDialog do it?我认为这是因为我实际上并没有在可视化树中创建控件,但是ContentDialog是如何做到的呢?

If I call ApplyTemplate() myself in ShowAsync() , it returns false and the template still isn't loaded.如果我自己在ShowAsync()中调用ApplyTemplate() ) ,它会返回false并且模板仍未加载。

How do I wrap a ContentDialog in a custom Control?如何将 ContentDialog 包装在自定义控件中?

Derive from this document源自本文档

Run code that can only work once the XAML-defined visual tree from templates has been applied.运行仅在应用模板中的 XAML 定义的可视化树后才能工作的代码。 For example, code that obtains references to named elements that came from a template, by calling GetTemplateChild, so that members of these parts can be referenced by other post-template runtime code.例如,通过调用 GetTemplateChild 获取对来自模板的命名元素的引用的代码,以便其他模板后运行时代码可以引用这些部分的成员。

If you just implement, but not add into visual tree.如果您只是实现,而不是添加到可视化树中。 OnApplyTemplate will not be invoke, and GetTemplateChild will return null. OnApplyTemplate不会被调用, GetTemplateChild将返回 null。 please declare in the xaml like the following.请在 xaml 中声明如下。

<Grid>
    <Button Click="Button_Click" Content="Open" />
    <local:ProgressDialog x:Name="Dialog" />
</Grid>

Or make a class that inherit ContentDialog directly, for more please refer this document .或者直接做一个继承ContentDialog的class,更多请参考这个文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM