rcarrington
rcarrington

Reputation: 1674

UWP: Template for custom control fails with "Failed to create a 'Windows.UI.Xaml.DependencyProperty' from the text" error

I am trying to create a custom ContentDialog control. My custom class likes:

public class ContentDialogEx : ContentDialog
{
    public string PrimaryButtonGlyph
    {
        get => (string)GetValue(PrimaryButtonGlyphProperty);
        set => SetValue(PrimaryButtonGlyphProperty, value);
    }

    public string SecondaryButtonGlyph
    {
        get => (string)GetValue(SecondaryButtonGlyphProperty);
        set => SetValue(SecondaryButtonGlyphProperty, value);
    }

    public string CloseButtonGlyph
    {
        get => (string)GetValue(CloseButtonGlyphProperty);
        set => SetValue(CloseButtonGlyphProperty, value);
    }

    public static readonly DependencyProperty PrimaryButtonGlyphProperty = DependencyProperty.Register(nameof(PrimaryButtonGlyph), typeof(string), typeof(ContentDialogEx), new PropertyMetadata(""));
    public static readonly DependencyProperty SecondaryButtonGlyphProperty = DependencyProperty.Register(nameof(SecondaryButtonGlyph), typeof(string), typeof(ContentDialogEx), new PropertyMetadata(""));
    public static readonly DependencyProperty CloseButtonGlyphProperty = DependencyProperty.Register(nameof(CloseButtonGlyph), typeof(string), typeof(ContentDialogEx), new PropertyMetadata(""));

    public ContentDialogEx()
    {
        Template = PrismUnityApplication.Current.Resources["ContentDialogExTemplate"] as ControlTemplate;
    }
}

The control template looks like:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:MyApp.Xaml.Controls">

    <ControlTemplate x:Key="ContentDialogExTemplate" TargetType="controls:ContentDialogEx">
    ...
    </ControlTemplate>
</ResourceDictionary>

The contents of the control template are copied from the default template and I have confirmed this works when I apply it to a standard ContentDialog.

This compiles fine and I can run the app but when I instantiate the dialog and try to show it I get the following error:

Failed to create a 'Windows.UI.Xaml.DependencyProperty' from the text 'Background'. [Line: 163 Position: 33]

If I try setting the TargetType of the ControlTemplate to ContentDialog I get the same error but it cannot find my custom property PrimaryButtonGlyph.

It is like it cannot find properties on the base class but if this was a problem then very little would work. What am I doing wrong?

(Target version: Windows 10, version 1803 (10.0; Build 17134), Min version: Windows 10 Fall Creators Update (10.0; Build 16299))

EDIT: I've created a demo solution here: https://www.dropbox.com/s/a4y7jrtcw3ivkqy/StackOverflow53506051.zip?dl=0

Upvotes: 0

Views: 540

Answers (1)

Nico Zhu
Nico Zhu

Reputation: 32785

From you code, you want to make custom Templated Control that inherit ContentDialog. But you have not initialized the default style. You could custom ContentDialog with following steps.

Create new items with Templated Control template.

enter image description here

After the ContentDialogTest.cs class created, the project will generate Generic.Xaml file automatically.

enter image description here

Please copy your ContentDialogExTemplate to Generic.Xaml file. Please not I have modified custom content dialog name to ContentDialogTest.

<Style TargetType="controls:ContentDialogTest" >
     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="controls:ContentDialogTest">
                <Border>
                   .........
                </Border>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
</Style>

Then create the DependencyProperty in ContentDialogTest class. you will find the there is this.DefaultStyleKey = typeof(ContentDialogTest); in the default constructor method. And this line make sure the style could be initialized.

public sealed class ContentDialogTest : ContentDialog
{
    public ContentDialogTest()
    {
        this.DefaultStyleKey = typeof(ContentDialogTest);
    }
    public string PrimaryButtonGlyph
    {
        get => (string)GetValue(PrimaryButtonGlyphProperty);
        set => SetValue(PrimaryButtonGlyphProperty, value);
    }

    public string SecondaryButtonGlyph
    {
        get => (string)GetValue(SecondaryButtonGlyphProperty);
        set => SetValue(SecondaryButtonGlyphProperty, value);
    }

    public string CloseButtonGlyph
    {
        get => (string)GetValue(CloseButtonGlyphProperty);
        set => SetValue(CloseButtonGlyphProperty, value);
    }

    public static readonly DependencyProperty PrimaryButtonGlyphProperty = DependencyProperty.Register
              (nameof(PrimaryButtonGlyph),
               typeof(string),
               typeof(ContentDialogTest),
               new PropertyMetadata("&#xF13E;"));

    public static readonly DependencyProperty SecondaryButtonGlyphProperty = DependencyProperty.Register
        (nameof(SecondaryButtonGlyph),
        typeof(string), typeof(ContentDialogTest),
        new PropertyMetadata("&#xF13D;"));

    public static readonly DependencyProperty CloseButtonGlyphProperty = DependencyProperty.Register
             (nameof(CloseButtonGlyph),
              typeof(string),
              typeof(ContentDialogTest),
              new PropertyMetadata("&#xF13D;"));
}

Usage

private async void OnShowContentDialogExButtonClick(object sender, RoutedEventArgs e)
{
    var dialog = new ContentDialogTest
    {
        Title = "Demo",
        Content = new Dialog(),

        PrimaryButtonText = "Primary",
        SecondaryButtonText = "Secondary",
        CloseButtonText = "Close"
    };

    await dialog.ShowAsync();
}

For better understanding, I have upload the code sample to git hub.

Upvotes: 1

Related Questions