Budding bro
Budding bro

Reputation: 33

How to change DataTemplate depending on API in WinUI?

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#?

Upvotes: 0

Views: 144

Answers (1)

Andrew KeepCoding
Andrew KeepCoding

Reputation: 13536

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>

Upvotes: 0

Related Questions