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.
OnApplyTemplatewill not be invoke, andGetTemplateChildwill return null. please declare in the xaml like the following.Or make a class that inherit ContentDialog directly, for more please refer this document.