Search code examples
wpfmvvmvisual-studio-2008user-controlsdependency-properties

Reusing WPF user control by parametrizing it does not work


In a MVVM application I have below user control.

From different areas of my WPF main Window, I am creating different instances of this user control so I would like to parametrize this user control in order to reuse it and show a different message in its label each time I create a new instance of it. In order to accomplish this, I have created a dependency property in the user control code-behind called MessageText and I have bound it to the label in the user control style.

User Control:

<UserControl x:Class="My.Apps.WPF.Demo.Controls.UCBusy"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">

    <UserControl.Resources>
        <Color x:Key="FilledColor" A="255" B="222" R="176" G="196"/>
        <Color x:Key="UnfilledColor" A="0" B="222" R="176" G="196"/>           

        <Style x:Key="BusyAnimationStyle" TargetType="Control">
            <Setter Property="Background" Value="white" />          

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Control">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="Animation0" BeginTime="00:00:00.0" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse0" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation1" BeginTime="00:00:00.2" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation2" BeginTime="00:00:00.4" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse2" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation3" BeginTime="00:00:00.6" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse3" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation4" BeginTime="00:00:00.8" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse4" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation5" BeginTime="00:00:01.0" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse5" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation6" BeginTime="00:00:01.2" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse6" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>

                            <Storyboard x:Key="Animation7" BeginTime="00:00:01.4" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse7" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>

                        <ControlTemplate.Triggers>                            
                            <Trigger Property="IsVisible" Value="True">                                                                

                                <Trigger.EnterActions>                                    
                                    <BeginStoryboard Storyboard="{StaticResource Animation0}" x:Name="Storyboard0" />
                                    <BeginStoryboard Storyboard="{StaticResource Animation1}" x:Name="Storyboard1"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation2}" x:Name="Storyboard2"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation3}" x:Name="Storyboard3"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation4}" x:Name="Storyboard4"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation5}" x:Name="Storyboard5"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation6}" x:Name="Storyboard6"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation7}" x:Name="Storyboard7"/>
                                </Trigger.EnterActions>

                                <Trigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="Storyboard0"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard1"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard2"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard3"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard4"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard5"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard6"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard7"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>

                        <Border BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" 
                                Background="{TemplateBinding Background}">

                            <Grid>
                                <Canvas Height="60" Width="60">
                                    <Canvas.Resources>
                                        <Style TargetType="Ellipse">
                                            <Setter Property="Width" Value="15"/>
                                            <Setter Property="Height" Value="15" />
                                            <Setter Property="Fill" Value="#009B9B9B" />
                                        </Style>
                                    </Canvas.Resources>

                                    <Ellipse x:Name="ellipse0" Canvas.Left="1.75" Canvas.Top="21"/>
                                    <Ellipse x:Name="ellipse1" Canvas.Top="7" Canvas.Left="6.5"/>
                                    <Ellipse x:Name="ellipse2" Canvas.Left="20.5" Canvas.Top="0.75"/>
                                    <Ellipse x:Name="ellipse3" Canvas.Left="34.75" Canvas.Top="6.75"/>
                                    <Ellipse x:Name="ellipse4" Canvas.Left="40.5" Canvas.Top="20.75" />
                                    <Ellipse x:Name="ellipse5" Canvas.Left="34.75" Canvas.Top="34.5"/>
                                    <Ellipse x:Name="ellipse6" Canvas.Left="20.75" Canvas.Top="39.75"/>
                                    <Ellipse x:Name="ellipse7" Canvas.Top="34.25" Canvas.Left="7" />
                                    <Ellipse Width="39.5" Height="39.5" Canvas.Left="8.75" Canvas.Top="8" Visibility="Hidden"/> 

                                    <Label Content="{Binding Path=MessageText}" 
                                           FontSize="17"
                                           Canvas.Left="60.5" Canvas.Top="11.5"
                                           HorizontalContentAlignment="Center" 
                                           VerticalAlignment="Center"/>

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

    <Control Style="{StaticResource BusyAnimationStyle}" />

</UserControl>

User Control Code-behind:

    public partial class UCBusy : UserControl
    {
        public UCBusy()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty MessageTextProperty =
DependencyProperty.Register("MessageText", typeof(string), typeof(UCBusy));
        public string MessageText
        {
            get
            {
                return this.GetValue(MessageTextProperty) as string;
            }
            set
            {
                this.SetValue(MessageTextProperty, value);
            }
        }
    }

Then in the view, I bind the user control dependency property just created with properties in view model:

View Model:

<!-- Instance 1 -->
<controls:UCBusy MessageText="{Binding Path=WaitMessageText_1}" />

<!-- Instance 2 -->
<controls:UCBusy MessageText="{Binding Path=WaitMessageText_2}" />

... and in view model ...

View Model:

            private string _waitMessageText_1 = "Hi there! I am message 1";
            private string _waitMessageText_2 = "Hi there! I am message 2";

            /// <summary>
            ///   Gets or sets the wait message text 1.
            /// </summary>
            public string WaitMessageText_1
            {
                get
                {
                    return _waitMessageText_1;
                }

                set
                {
                    if (_waitMessageText_1 == value) return;
                    _waitMessageText_1 = value;

                    OnPropertyChanged("WaitMessageText_1");
                }
            }

            /// <summary>
            ///   Gets or sets the wait message text 2.
            /// </summary>
            public string WaitMessageText_2
            {
                get
                {
                    return _waitMessageText_2;
                }

                set
                {
                    if (_waitMessageText_2 == value) return;
                    _waitMessageText_2 = value;

                    OnPropertyChanged("WaitMessageText_2");
                }
            }

Finally, from view model I am setting these properties when needed but I note that my view is not being updated with the new messages I put, I mean, label in the user control does not display nothing. What am I doing wrong? I think I am missing something anywhere...

Note: In my case, Datacontext is always the same (I have set it to point to view model) so no need to change it each time I create a new instance of user control.


Solution

  • I would have you start by taking a look at a prior answer I provided that did a bunch of each step on a customized control, properties, styling, etc. It too is here at S/O

    A couple of direct issues... Your "Style" declaration is based on a "Control", but your class is based on "Control", but your custom class is explicitly a "UCBusy" control, so "Control" has no idea what "MessageText" is for the style binding.

    Also, you got by it partially because you declared as a different class type.

    EDITED WITH FULL SAMPLE per my previous suggestions. Here is source code that works to see all the parts. I created a new project "StackHelp" and have the following. Notice the merged dictionary is referring to the "component/MyClasses…" subfolder where my custom classes and corresponding .xaml resource dictionaries are created.

    APP.XAML

    <Application 
        x:Class="StackHelp.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="MyMainWindow.xaml">
    
        <Application.Resources>
            <!-- Generic up front for the entire application for the theme / styles to be used -->
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary  Source="pack://application:,,,/StackHelp;component/MyClasses/UCBusy.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    MyClasses\UCBusy.cs (within the subfolder in the project)

    using System.Windows;
    using System.Windows.Controls;
    
    namespace StackHelp.MyClasses
    {
        public class UCBusy : UserControl
        {
            public UCBusy()
            {
                // just to default so style will allow us to see where this will present
                // even just during design time sample.
                MessageText = "My Sample Text";
            }
    
            public static readonly DependencyProperty MessageTextProperty
                = DependencyProperty.Register("MessageText",
                typeof(string), typeof(UCBusy));
            public string MessageText
            {
                get { return GetValue(MessageTextProperty) as string; }
                set { SetValue(MessageTextProperty, value); }
            }
        }
    }
    

    MyClasses\UCBusy.xaml (the xaml is specifically RESOURCE DICTIONARY item) Two styles defined... a basic just as a stand-alone label just to see HOW the bindings get done... A SECOND one specifically to do your elaborate style. The "xmlns:myC" means the "myC" alias refers to the classes found within the "MyClasses" subfolder of the project per namespace.

    <ResourceDictionary 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myC="clr-namespace:StackHelp.MyClasses">
    
        <!-- resource dictionary is in-itself a list of resources -->
    
        <!-- Just a SIMPLE Style to test the proper bindings... as basic as possible to test context working -->
        <Style TargetType="{x:Type myC:UCBusy}" x:Key="BusyAnimationStyleBasic">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type myC:UCBusy}" >
                        <Label Content="{TemplateBinding MessageText}" 
                            FontSize="17"
                            HorizontalContentAlignment="Center" 
                            VerticalAlignment="Center"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
    
        <Color x:Key="FilledColor" A="255" B="222" R="176" G="196"/>
        <Color x:Key="UnfilledColor" A="0" B="222" R="176" G="196"/>
    
    
        <!-- Now, your elaborate style with all animations...-->
        <Style TargetType="{x:Type myC:UCBusy}" x:Key="BusyAnimationStyle">
            <Setter Property="Background" Value="white" />
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type myC:UCBusy}" >
    
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="Animation0" BeginTime="00:00:00.0" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse0" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation1" BeginTime="00:00:00.2" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation2" BeginTime="00:00:00.4" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse2" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation3" BeginTime="00:00:00.6" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse3" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation4" BeginTime="00:00:00.8" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse4" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation5" BeginTime="00:00:01.0" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse5" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation6" BeginTime="00:00:01.2" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse6" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
    
                            <Storyboard x:Key="Animation7" BeginTime="00:00:01.4" RepeatBehavior="Forever">
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="ellipse7" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                    <SplineColorKeyFrame KeyTime="00:00:00.0" Value="{StaticResource FilledColor}"/>
                                    <SplineColorKeyFrame KeyTime="00:00:01.6" Value="{StaticResource UnfilledColor}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>
    
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsVisible" Value="True">
    
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource Animation0}" x:Name="Storyboard0" />
                                    <BeginStoryboard Storyboard="{StaticResource Animation1}" x:Name="Storyboard1"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation2}" x:Name="Storyboard2"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation3}" x:Name="Storyboard3"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation4}" x:Name="Storyboard4"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation5}" x:Name="Storyboard5"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation6}" x:Name="Storyboard6"/>
                                    <BeginStoryboard Storyboard="{StaticResource Animation7}" x:Name="Storyboard7"/>
                                </Trigger.EnterActions>
    
                                <Trigger.ExitActions>
                                    <StopStoryboard BeginStoryboardName="Storyboard0"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard1"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard2"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard3"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard4"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard5"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard6"/>
                                    <StopStoryboard BeginStoryboardName="Storyboard7"/>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
    
    
                        <!--<StackPanel Orientation="Horizontal">
                            <TextBlock Text="{TemplateBinding MessageText}"/>
                        </StackPanel>-->
    
                        <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}">
    
                            <Grid>
                                <Canvas Height="60" Width="60">
                                    <Canvas.Resources>
                                        <Style TargetType="Ellipse">
                                            <Setter Property="Width" Value="15"/>
                                            <Setter Property="Height" Value="15" />
                                            <Setter Property="Fill" Value="#009B9B9B" />
                                        </Style>
                                    </Canvas.Resources>
    
                                    <Ellipse x:Name="ellipse0" Canvas.Left="1.75" Canvas.Top="21"/>
                                    <Ellipse x:Name="ellipse1" Canvas.Top="7" Canvas.Left="6.5"/>
                                    <Ellipse x:Name="ellipse2" Canvas.Left="20.5" Canvas.Top="0.75"/>
                                    <Ellipse x:Name="ellipse3" Canvas.Left="34.75" Canvas.Top="6.75"/>
                                    <Ellipse x:Name="ellipse4" Canvas.Left="40.5" Canvas.Top="20.75" />
                                    <Ellipse x:Name="ellipse5" Canvas.Left="34.75" Canvas.Top="34.5"/>
                                    <Ellipse x:Name="ellipse6" Canvas.Left="20.75" Canvas.Top="39.75"/>
                                    <Ellipse x:Name="ellipse7" Canvas.Top="34.25" Canvas.Left="7" />
                                    <Ellipse Width="39.5" Height="39.5" Canvas.Left="8.75" Canvas.Top="8" Visibility="Hidden"/>
    
                                    <Label Content="{TemplateBinding MessageText}" 
                                        FontSize="17"
                                        Canvas.Left="60.5" Canvas.Top="11.5"
                                        HorizontalContentAlignment="Center" 
                                        VerticalAlignment="Center"/>
    
                                </Canvas>
                            </Grid>
                        </Border>
    
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
    </ResourceDictionary>
    

    MyMainWindow.xaml.cs (the main window for the startup of the application)

    using System.ComponentModel;
    using System.Windows;
    
    namespace StackHelp
    {
        public partial class MyMainWindow : Window, INotifyPropertyChanged
        {
            public MyMainWindow()
            {
                DataContext = this;
                InitializeComponent();
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
    
            private string _waitMessageText_1 = "Hi there! I am message 1";
            public string WaitMessageText_1
            {
                get
                {
                    return _waitMessageText_1;
                }
    
                set
                {
                    if (_waitMessageText_1 == value) return;
                    _waitMessageText_1 = value;
    
                    OnPropertyChanged("WaitMessageText_1");
                }
            }
    
            private string _waitMessageText_2 = "Hi there! I am message 2";
            public string WaitMessageText_2
            {
                get
                {
                    return _waitMessageText_2;
                }
    
                set
                {
                    if (_waitMessageText_2 == value) return;
                    _waitMessageText_2 = value;
    
                    OnPropertyChanged("WaitMessageText_2");
                }
            }
        }
    }
    

    MyMainWindow.xaml (actual xaml for the main window) Here, I have two instances, one using the BASIC style, second using the fully defined/spinner style.

    <Window x:Class="StackHelp.MyMainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:myC="clr-namespace:StackHelp.MyClasses"
        Title="My Main Window" Height="250" Width="800">
    
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
    
            <!-- Instance 1 using the BASIC style version-->
            <myC:UCBusy MessageText="{Binding WaitMessageText_1}" 
                Grid.Column="0" Style="{StaticResource BusyAnimationStyleBasic}" />
    
            <!-- Instance 2 using the FINAL style version-->
            <myC:UCBusy MessageText="{Binding WaitMessageText_2}" 
                Grid.Column="1" Style="{StaticResource BusyAnimationStyle}"/>
    
        </Grid>
    </Window>
    

    Hope this finishes jump-starting you on your own styles and implementations.