0

I have 6 DataTemplate for this API. API is a enum.

public enum ShimmerType 
{
    CirclePersona,
    SquarePersona,
    Profile,
    Article,
    Video,
    Feed,
    Shopping,
}

API name is Type. I defined this property in below of my shimmer control.

public ShimmerType Type
{
    get { return (ShimmerType)GetValue(TypeProperty); }
    set { SetValue(TypeProperty, value); }
}

// Using a DependencyProperty as the backing store for Type.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type", typeof(ShimmerType), typeof(SfShimmer), new PropertyMetadata(ShimmerType.CirclePersona,OnTypePropertyChangedMethod));

In my ShimmerControl.XAML:

I have given a sample data template for your understanding.

<DataTemplate x:Key="ShimmerFeedTemplate">
    <!--Blah Blah blah -->
</DataTemplate>
<DataTemplate x:Key="ShimmerCirclePersonaTemplate">
    <!--Blah Blah blah -->
</DataTemplate>
<DataTemplate x:Key="ShimmerArticleStyle">
    <!--Blah Blah blah -->
</DataTemplate>
<DataTemplate x:Key="ShimmerProfileTemplate">
    <!--Blah Blah blah -->
</DataTemplate>
<DataTemplate x:Key="ShimmerShoppingTemplate">
    <!--Blah Blah blah -->
</DataTemplate>
<DataTemplate x:Key="ShimmerVideoTemplate">
    <!--Blah Blah blah -->
</DataTemplate>

Shimmer Style:

I've given you a control templates in the Shimmer style. I have provided content template as CirclePersona template by with shimmer control.

<Style x:Key="ShimmerStyle" TargetType="local:Shimmer">
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Fill" Value="{ThemeResource ShimmerFillColor}"/>
    <Setter Property="Template"> 
        <Setter.Value>
            <ControlTemplate TargetType="local:Shimmer">
                <StackPanel>
                    <ContentControl x:Name="Grid1">
                        <ContentPresenter x:Name="presenters" ContentTemplate="{StaticResource ShimmerCirclePersonaTemplate}" />
                    </ContentControl>
                    <Grid x:Name="Grid2">
                        <ContentControl>
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </ContentControl>
                    </Grid>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

How to change the DataTemplate of my Control ContentPresenter to according the Type API .I have set a separate datatemplate for each enum type API.

I have Try below this:

public class SfShimmer:Control
{
    public SfShimmer()                                   
    {
        this.DefaultStyleKey= typeof(SfShimmer);
    }
       
    internal ContentPresenter Presenter;

    public ShimmerType Type
    {
        get { return (ShimmerType)GetValue(TypeProperty); }
        set { SetValue(TypeProperty, value); }
    }

    public static readonly DependencyProperty TypeProperty =
        DependencyProperty.Register("Type", typeof(ShimmerType), typeof(SfShimmer), new PropertyMetadata(ShimmerType.CirclePersona,OnTypePropertyChangedMethod));

    protected override void OnApplyTemplate()
    {  
        this.Presenter = this.GetTemplateChild("presenters") as ContentPresenter;
        base.OnApplyTemplate();
        this.Loaded += SfShimmer_Loaded;
    }
 
    private static void OnTypePropertyChangedMethod(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SfShimmer sfShimmer = d as SfShimmer;
        ContentPresenter pr = sfShimmer.Presenter;
        if (pr != null)
        {
            DataTemplate dataTemplate = null;
            switch (sfShimmer.Type)
            {
                case ShimmerType.Feed:
                    dataTemplate = sfShimmer.Resources["ShimmerFeedControlTemplate"] as DataTemplate;
                    break;
                case ShimmerType.Profile:
                    dataTemplate = sfShimmer.Resources["ShimmerProfileTemplate"] as DataTemplate;
                    break;
                case ShimmerType.Video:
                    dataTemplate = sfShimmer.Resources["ShimmerVideoTemplate"] as DataTemplate;
                    break;
                case ShimmerType.Shopping:
                    dataTemplate = sfShimmer.Resources["ShimmerShoppingTemplate"] as DataTemplate;
                    break;
                default:
                    dataTemplate = sfShimmer.Resources["ShimmerFeedControlTemplate"] as DataTemplate;
                    break;
            }
            pr.ContentTemplate = dataTemplate;
        }
    }
}

I tried this but no progress. In WinUI MainWindow.Xaml I specified this API like below:

<Window
    x:Class="WinUI_3_SFShimmer_control.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUI_3_SFShimmer_control"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:shim="using:Shimmer.WinUI">

    <Grid>
        <shim:Shimmer x:Name="shimmer" Type="Profile" />
    </Grid>
</Window>    

The dataTemplate should be the same as the contenttemplate of my content control, depending on what type I give to my Type API in the mainwindow.xaml. How in WinUI C#?

Florian
  • 1,019
  • 6
  • 22

1 Answers1

0

You can create yourown DataTemplateSelector.

This is a simple example based on a bit of your code:

public enum ShimmerType
{
    CirclePersona,
    SquarePersona,
    Profile,
}

public class ShimmerTemplateSelector : DataTemplateSelector
{
    public DataTemplate? CirclePersonaTemplate { get; set; }

    public DataTemplate? SquarePersonaTemplate { get; set; }

    public DataTemplate? ProfileTemplate { get; set; }

    protected override DataTemplate? SelectTemplateCore(object item)
    {
        return (item as CustomButton)?.ShimmerType switch
        {
            ShimmerType.CirclePersona => CirclePersonaTemplate,
            ShimmerType.SquarePersona => SquarePersonaTemplate,
            ShimmerType.Profile => ProfileTemplate,
            _ => base.SelectTemplateCore(item),
        };
    }
}

public class CustomButton : Button
{
    public static readonly DependencyProperty ShimmerTypeProperty =
        DependencyProperty.Register(
            nameof(ShimmerType),
            typeof(ShimmerType),
            typeof(CustomButton),
            new PropertyMetadata(ShimmerType.CirclePersona, OnShimmerTypePropertyChanged));

    public ShimmerType ShimmerType
    {
        get => (ShimmerType)GetValue(ShimmerTypeProperty);
        set => SetValue(ShimmerTypeProperty, value);
    }

    private static void OnShimmerTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is CustomButton button)
        {
            button.ContentTemplate = button.ContentTemplateSelector.SelectTemplate(button);
        }
    }
}
<MainWindow
...
...>

    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="CirclePersonaDataTemplate">
                <TextBlock Text="CirclePersona" />
            </DataTemplate>
            <DataTemplate x:Key="SquarePersonaDataTemplate">
                <TextBlock Text="SquarePersona" />
            </DataTemplate>
            <DataTemplate x:Key="ProfileDataTemplate">
                <TextBlock Text="Profile" />
            </DataTemplate>
            <local:ShimmerTemplateSelector
                x:Key="ShimmerTemplateSelector"
                CirclePersonaTemplate="{StaticResource CirclePersonaDataTemplate}"
                ProfileTemplate="{StaticResource ProfileDataTemplate}"
                SquarePersonaTemplate="{StaticResource SquarePersonaDataTemplate}" />
        </Grid.Resources>

        <Grid>
            <local:CustomButton
                Content="?"
                ContentTemplateSelector="{StaticResource ShimmerTemplateSelector}"
                ShimmerType="Profile" />
        </Grid>
    </Grid>
</MainWindow>
Community
  • 1
  • 1
Andrew KeepCoding
  • 7,040
  • 2
  • 14
  • 21
  • I have a [video](https://youtu.be/MPUue7mg4EE) about how to declare a Dictionary of DataTemplates in XAML and use it for a DataTemplateSelector. This way you don't need to modify the DataTemplateSelector when you modifiy your ShimmerType. – Andrew KeepCoding May 12 '23 at 14:09
  • Please share the video link .link are not worked . Unlike you upgraded and Without using buttons. Is it possible to get the corresponding data template by giving value only to the API property mentioned in the above MainWindow.xaml page?. For example I have set the profile for type DBay. Can you get profile templates with just this?. – Budding bro May 15 '23 at 05:16
  • I updated my answer. The ``MainWindow`` cannot have resources, so you can't do ````. Instead you can do ```` or ````. – Andrew KeepCoding May 15 '23 at 05:27
  • By using either the control template or the data template. How do I get the templates to match my control's API?. Are there any solutions. Note, only Type API should be mentioned in mainwindow. xaml page – Budding bro May 15 '23 at 05:30
  • Sorry, I don't understand your question. By API you mean your ``enum ShimmerType`` right? – Andrew KeepCoding May 15 '23 at 05:40
  • Yes. API means Type property. Type="Profile" – Budding bro May 15 '23 at 05:45
  • I don't understand what's the problem with my answer. – Andrew KeepCoding May 15 '23 at 05:47
  • Should my control style inside specify ContentTemplate or ContentTemplateSelector? . Update the style above. – Budding bro May 15 '23 at 11:36
  • 1
    A ``ContentTemplate`` should do. Note that my answer is based on a ``DataTemplateSelector``. Instead of style, it uses ``DataTemplate``s depending on the ShimmerType. – Andrew KeepCoding May 15 '23 at 12:39