简体   繁体   中英

Animating WPF ImageBrush in ProgressBar Control Template

I have a Control Template for Progress Bar in my Resource Dictionary. Complete code goes like this:

<ControlTemplate x:Key="KinasticPB" TargetType="ProgressBar">

  <ControlTemplate.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard>
                <Storyboard x:Name="str">
                    <QuaternionAnimation x:Name="quatanim"
                                         Storyboard.TargetProperty="(ImageBrush.Viewport)"
                                         From="0,0,36,36" 
                                         To="36,0,36,36" 
                                         Duration="0:0:5" 
                                         AutoReverse="False" 
                                         RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </ControlTemplate.Triggers>

    <!-- Custom progress bar goes here -->
    <Border Name="PART_Track" 
            Width="{TemplateBinding Width}"
            BorderBrush="{TemplateBinding BorderBrush}" 
            BorderThickness="{TemplateBinding BorderThickness}" 
            Background="{TemplateBinding Background}" 
            Height="{TemplateBinding Height}"
            CornerRadius="0"
            Padding="1.5" >

        <Grid>
            <!-- Rounded mask (stretches to fill Grid) -->
            <Border Name="mask" Background="#EEEEEE" CornerRadius="0"/>

            <!-- Any content -->

            <Rectangle Name="PART_Indicator" HorizontalAlignment="Left" Height="{TemplateBinding Height}">

                <Rectangle.OpacityMask>
                    <VisualBrush Visual="{Binding ElementName=mask}" />
                </Rectangle.OpacityMask>

                <Rectangle.Fill>

                    <ImageBrush x:Name="imgbrush"
                                ImageSource="/Kinastic.UCLibrary;component/Media/tex.png" 
                                AlignmentX="Left" 
                                Stretch="Fill" 
                                TileMode="Tile" 
                                AlignmentY="Top" 
                                ViewportUnits="Absolute" 
                                Viewport="0,0,36,36" 
                                ViewboxUnits="RelativeToBoundingBox" 
                                Viewbox="0,0,1,1"
                                >
                    </ImageBrush>

                </Rectangle.Fill>

            </Rectangle>

        </Grid>

    </Border>

</ControlTemplate>

But the animation won't work. What I want to achieve is create an animated progress bar filling. I figured it out, that I only need to change ImageBrush's viewport values. Probably it is TargetProperty which is wrong.

To animate a rect (the ViewPort type) use a RectAnimation rather than a QuaternionAnimation. The storyboard.TargetName property of the animation needs be set to imgbrush as well. Try:

<ControlTemplate
    x:Key="KinasticPB"
    TargetType="ProgressBar">    
    <ControlTemplate.Triggers>
        <EventTrigger
            RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard>
                <Storyboard
                    x:Name="str">
                    <RectAnimation
                        x:Name="quatanim"
                        Storyboard.TargetName="imgbrush"
                        Storyboard.TargetProperty="(ImageBrush.Viewport)"
                        From="0,0,36,36"
                        To="36,0,36,36"
                        Duration="0:0:5"
                        AutoReverse="False"
                        RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </ControlTemplate.Triggers>

    <!-- Custom progress bar goes here -->
    <Border
        Name="PART_Track"
        Width="{TemplateBinding Width}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        Background="{TemplateBinding Background}"
        Height="{TemplateBinding Height}"
        CornerRadius="0"
        Padding="1.5">

        <Grid>
            <!-- Rounded mask (stretches to fill Grid) -->
            <Border
                Name="mask"
                Background="#EEEEEE"
                CornerRadius="0" />

            <!-- Any content -->

            <Rectangle
                Name="PART_Indicator"
                HorizontalAlignment="Left"
                Height="{TemplateBinding Height}">    
                <Rectangle.OpacityMask>
                    <VisualBrush
                        Visual="{Binding ElementName=mask}" />
                </Rectangle.OpacityMask>    
                <Rectangle.Fill>    
                    <ImageBrush
                        x:Name="imgbrush"
                        ImageSource="/Kinastic.UCLibrary;component/Media/tex.png"
                        AlignmentX="Left"
                        Stretch="Fill"
                        TileMode="Tile"
                        AlignmentY="Top"
                        ViewportUnits="Absolute"
                        Viewport="0,0,36,36"
                        ViewboxUnits="RelativeToBoundingBox"
                        Viewbox="0,0,1,1">
                    </ImageBrush>    
                </Rectangle.Fill>    
            </Rectangle>    
        </Grid>    
    </Border>    
</ControlTemplate>

The problem is back. I had to change it to UserControl, to put some code behind it and it doesn't work again. I am getting XamlParseException at line

<ProgressBar Width="{Binding ElementName=Width}" Name="ProgressBar" Height="{Binding ElementName=Height}" Value="20" />

However, when I comment the ControlTemplate.Trigger section, it works well.

<UserControl x:Class="Kinastic.UCLibrary.AnimatedProgressBar"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" d:DesignHeight="30" d:DesignWidth="300" Height="30" Width="300">
<UserControl.Resources>

    <!--<Storyboard x:Name="str" x:Key="str1">
        <RectAnimation x:Name="quatanim"
    Storyboard.TargetName="imgbrush" 
            Storyboard.TargetProperty="(ImageBrush.Viewport)"
    From="0,0,36,36" To="36,0,36,36" Duration="0:0:5" 
    AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>-->

    <Style TargetType="ProgressBar">
        <Setter Property="Width" Value="100" />
        <Setter Property="Height" Value="10" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="#666666" />
        <Setter Property="BorderThickness" Value="1.6" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate x:Name="KinasticPB" TargetType="ProgressBar">
                    <ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                            <BeginStoryboard>
                                <Storyboard x:Name="str">
                                    <RectAnimation
                                        x:Name="rectanim"
                                        Storyboard.TargetName="{DynamicResource imgbrush}"
                                        Storyboard.TargetProperty="(ImageBrush.Viewport)"
                                        From="0,0,36,36"
                                        To="36,0,36,36"
                                        Duration="0:0:5"
                                        AutoReverse="False"
                                        RepeatBehavior="Forever" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                    <!-- Custom progress bar goes here -->
                    <Border Name="PART_Track" 
                            Width="{TemplateBinding Width}"
                            BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}" 
                            Height="{TemplateBinding Height}"
                            CornerRadius="0"
                            Padding="1.5" >

                        <Grid>

                            <!-- Rounded mask (stretches to fill Grid) -->
                            <Border Name="mask" Background="#EEEEEE" CornerRadius="0"/>



                            <!-- Any content -->

                            <Rectangle Name="PART_Indicator" HorizontalAlignment="Left" Height="{TemplateBinding Height}">
                                <Rectangle.OpacityMask>
                                    <VisualBrush Visual="{Binding ElementName=mask}" />
                                </Rectangle.OpacityMask>
                                <Rectangle.Fill>

                                    <ImageBrush 
                                            x:Name="imgbrush"

                                            ImageSource="/Kinastic.UCLibrary;component/Media/tex.png" 
                                            AlignmentX="Left" 
                                            Stretch="Fill" 
                                            TileMode="Tile" 
                                            AlignmentY="Top" 
                                            ViewportUnits="Absolute" 
                                            Viewport="0,0,36,36" 
                                            ViewboxUnits="RelativeToBoundingBox" 
                                            Viewbox="0,0,1,1"
                                            >

                                    </ImageBrush>
                                </Rectangle.Fill>

                            </Rectangle>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>




<ProgressBar 
    Width="{Binding ElementName=Width}" 
    Name="ProgressBar" 
    Height="{Binding ElementName=Height}" 
    Value="20" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM