You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI中如何根据枚举Type属性为Shimmer控件匹配对应样式?

问题描述

我在WinUI中为自定义Shimmer控件编写了7个Style,所有Style的TargetType均为local:Shimmer。该控件拥有一个枚举类型的Type依赖属性,期望在MainWindow.xaml中指定Type属性值(如Feed)时,控件自动应用对应类型的样式。

现有代码示例

Style 示例(以Feed、Video、Profile为例)

<!-- ShimmerFeedStyle -->
<Style x:Key="ShimmerFeedStyle" 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>
                    <Grid x:Name="Grid1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Ellipse Grid.Column="0" Grid.Row="0" Height="100" Width="100" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left" />
                        <Rectangle x:Name="rect1" Margin="120,0,0,40" Grid.Row="0" Grid.Column="0" Height="30" Width="500" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left"/>
                        <Rectangle x:Name="rect2" Margin="120,50,0,0" Grid.Row="0" Grid.Column="0" Height="30" Width="300" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left"/>
                        <Rectangle Grid.Row="1" Grid.Column="0" Fill="{TemplateBinding Fill}" Margin="0,30,0,0" Height="200" Width="625" HorizontalAlignment="Left"/>
                        <Rectangle Grid.Row="2" Grid.Column="0" Fill="{TemplateBinding Fill}" Margin="0,20,0,0" Height="20" Width="625" HorizontalAlignment="Left"/>
                        <Rectangle Grid.Row="3" Grid.Column="0" Fill="{TemplateBinding Fill}" Margin="0,20,0,0" Height="20" Width="625" HorizontalAlignment="Left"/>
                    </Grid>
                    <Grid x:Name="Grid2">
                        <ContentControl>
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </ContentControl>
                    </Grid>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- ShimmerVideoStyle -->
<Style x:Key="ShimmerVideoStyle" 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>
                    <Grid x:Name="Grid1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="auto"/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <Rectangle Grid.Row="0" Grid.Column="0" Fill="{TemplateBinding Fill}" Margin="0,20,0,0" Height="250" Width="625" HorizontalAlignment="Left"/>
                        <Ellipse Grid.Row="1" Grid.Column="0" Height="100" Width="100" Margin="0,40,0,0" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left"/>
                        <Rectangle Margin="130,30,0,30" Grid.Row="1" Grid.Column="0" Height="28" Width="400" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left"/>
                        <Rectangle Margin="130,80,0,0" Grid.Row="1" Grid.Column="0" Height="28" Width="400" Fill="{TemplateBinding Fill}" HorizontalAlignment="Left"/>
                    </Grid>
                    <Grid x:Name="Grid2">
                        <ContentControl>
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </ContentControl>
                    </Grid>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- ShimmerProfileStyle -->
<Style x:Key="ShimmerProfileStyle" 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>
                    <Grid x:Name="Grid1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="auto"/>
                            <RowDefinition Height="auto"/>
                            <RowDefinition Height="auto"/>
                            <RowDefinition Height="auto"/>
                            <RowDefinition Height="auto"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                        <Ellipse Grid.Row="0" Grid.Column="0" Height="100" Width="100" Fill="{TemplateBinding Fill}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        <Rectangle Grid.Row="1" Grid.Column="0" Height="30" Width="150" Margin="0,45,0,0" Fill="{TemplateBinding Fill}" HorizontalAlignment="Center"/>
                        <Rectangle Grid.Row="2" Grid.Column="0" Height="30" Width="300" Margin="0,15,0,0" Fill="{TemplateBinding Fill}" HorizontalAlignment="Center"/>
                        <Rectangle Grid.Row="3" Grid.Column="0" Height="25" Width="500" Margin="0,40,0,0" Fill="{TemplateBinding Fill}" HorizontalAlignment="Center"/>
                        <Rectangle Grid.Row="4" Grid.Column="0" Height="25" Width="500" Margin="0,20,0,0" Fill="{TemplateBinding Fill}" HorizontalAlignment="Center"/>
                    </Grid>
                    <Grid x:Name="Grid2">
                        <ContentControl>
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </ContentControl>
                    </Grid>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MainWindow.xaml 代码

<shim:Shimmer x:Name="shimmer" IsActive="True" Type="Feed">
    <shim:Shimmer.Content>
        <Grid>
            <Image Height="100" Width="100" Source="D:\WinUI-3 Shimmer control\Syncfusion.Shimmer.WinUI\Shimmer\download.jfif"/>
            <TextBlock Text="Content is Loaded!" />
        </Grid>
    </shim:Shimmer.Content>
</shim:Shimmer>

Shimmer 类代码

public class Shimmer : Control
{
    public Shimmer()                                   
    {
        this.DefaultStyleKey = typeof(Shimmer);
    }

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

    // 使用依赖属性作为Type的后备存储,支持动画、样式、绑定等
    public static readonly DependencyProperty TypeProperty =
        DependencyProperty.Register("Type", typeof(ShimmerType), typeof(SfShimmer), new PropertyMetadata(null, OnTypePropertyChanged));
}
解决方案

首先修正Shimmer类中的两处错误:

  1. 依赖属性的所有者类型应为Shimmer,而非SfShimmer
  2. 枚举类型的依赖属性默认值不能为null,需设置枚举的默认值(比如ShimmerType.Feed)

修正后的Shimmer类基础代码:

public enum ShimmerType
{
    Feed,
    Video,
    Profile
    // 其他枚举值...
}

public class Shimmer : Control
{
    public Shimmer()                                   
    {
        this.DefaultStyleKey = typeof(Shimmer);
    }

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

    public static readonly DependencyProperty TypeProperty =
        DependencyProperty.Register("Type", typeof(ShimmerType), typeof(Shimmer), new PropertyMetadata(ShimmerType.Feed, OnTypePropertyChanged));

    private static void OnTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var shimmer = d as Shimmer;
        shimmer?.UpdateStyle();
    }
}

下面提供两种可行的自动切换样式方案:

方案1:代码逻辑切换样式

在Type属性变更时,根据枚举值拼接对应的Style Key,从资源中获取并应用样式。

在Shimmer类中添加UpdateStyle方法:

private void UpdateStyle()
{
    string styleKey = $"Shimmer{Type}Style";
    if (Application.Current.Resources.TryGetValue(styleKey, out object resource) && resource is Style style)
    {
        this.Style = style;
    }
}
  • 确保所有Style都在全局资源字典中(如App.xaml),或控件所在上下文的资源字典中

方案2:XAML DataTrigger切换模板

定义一个默认的Shimmer样式,通过DataTrigger绑定Type属性,根据不同枚举值切换对应的ControlTemplate,完全通过XAML实现,无需额外代码逻辑。

步骤1:提取ControlTemplate为独立资源

<!-- 提取各类型的ControlTemplate作为全局资源 -->
<ControlTemplate x:Key="ShimmerFeedTemplate" TargetType="local:Shimmer">
    <!-- 原ShimmerFeedStyle中的ControlTemplate内容 -->
</ControlTemplate>

<ControlTemplate x:Key="ShimmerVideoTemplate" TargetType="local:Shimmer">
    <!-- 原ShimmerVideoStyle中的ControlTemplate内容 -->
</ControlTemplate>

<ControlTemplate x:Key="ShimmerProfileTemplate" TargetType="local:Shimmer">
    <!-- 原ShimmerProfileStyle中的ControlTemplate内容 -->
</ControlTemplate>

步骤2:定义默认Style并添加DataTrigger

<Style TargetType="local:Shimmer">
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Fill" Value="{ThemeResource ShimmerFillColor}"/>
    <Setter Property="Template" Value="{StaticResource ShimmerFeedTemplate}"/> <!-- 默认模板 -->
    <Style.Triggers>
        <DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource Self}}" Value="Video">
            <Setter Property="Template" Value="{StaticResource ShimmerVideoTemplate}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource Self}}" Value="Profile">
            <Setter Property="Template" Value="{StaticResource ShimmerProfileTemplate}"/>
        </DataTrigger>
        <!-- 为其他枚举值添加对应的DataTrigger -->
    </Style.Triggers>
</Style>

内容的提问来源于stack exchange,提问作者Budding developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:37:02