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. I figured I could do this by deriving from Control
and creating a ContentDialog
inside of its ControlTemplate
.
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
:
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. My OnApplyTemplate
method is never called, so _dialog
doesn't get wired up. I assume this is because I'm not actually creating the control in the visual tree, but then how does ContentDialog
do it?
If I call ApplyTemplate()
myself in ShowAsync()
, it returns false
and the template still isn't loaded.
Derive from this document
If you just implement, but not add into visual tree.
OnApplyTemplate
will not be invoke, andGetTemplateChild
will return null. please declare in the xaml like the following.Or make a class that inherit ContentDialog directly, for more please refer this document.