Wednesday 26 February 2014

Create a 5 star rating control in xaml

        In this post we are going to see how to create a 5 star rating control in xaml, normally in the blogs or the advertise a product consists of ratings to specify how much it is worth for it, this control can be created easily in the xaml, for this we have to use the toggle button because it have the state like checked and unchecked.


First launch the visual studio and create project as rating control add a user control xaml in it. and add reference to it.

For the rating control we have to use the toggle button, so we have to create the Template for the toggle button, which have a viewbox consists of path drawn for the rating control, along with the template triggers on IsChecked.

When the Rating control is clicked, we are get the value from the rating control which is present in Tag.Fetch the value and assign to the dependency property. we have to limit the value of the rating with in 0 to 5 in the property set assessor.

Output:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RatingControl
{
    /// <summary>
    /// Interaction logic for Rating.xaml
    /// </summary>
    public partial class Rating : UserControl
    {
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Rating",typeof(int),typeof(Rating),
            new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,new PropertyChangedCallback(RatingChanged)));

        private int _max = 5;

        public int Value
        {
            get
            {
                return (int)GetValue(ValueProperty);
            }
            set
            {
                if(value<0)
                {
                    SetValue(ValueProperty,0);
                }
                else if(value>_max)
                {
                    SetValue(ValueProperty,_max);
                }
                else
                {
                   SetValue(ValueProperty,value);
                }
            }
        }

        private static void RatingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
               Rating item = sender as Rating;
            int newval = (int)e.NewValue;
            UIElementCollection childs= ((Grid)(item.Content)).Children;

            ToggleButton button = null;

            for(int i=0;i<newval;i++)
            {
                button = childs[i] as ToggleButton;
                if(button!=null)
                    button.IsChecked = true;
            }

            for(int i=newval;i<childs.Count;i++)
            {
                button = childs[i] as ToggleButton;
                if(button!=null)
                    button.IsChecked = false;
            }

        }

        private void ClickEventHandler(object sender,RoutedEventArgs args)
        {
            ToggleButton  button = sender as ToggleButton;
            int newvalue = int.Parse(button.Tag.ToString());
           Value = newvalue;
        }
       
        public Rating()
        {
            InitializeComponent();
        }
    }
}


Xaml:

<UserControl x:Class="RatingControl.Rating"
             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="300" d:DesignWidth="300">
    <Grid>
        <Grid.Resources>
            <ControlTemplate x:Key="ratingtemplate" TargetType="{x:Type ToggleButton}">
                <Viewbox>
                    <Path Name="star" Fill="White" Data="F1 M 145.637,174.227L 127.619,110.39L 180.809,70.7577L 114.528,68.1664L 93.2725,5.33333L 70.3262,67.569L 4,68.3681L 56.0988,109.423L 36.3629,172.75L 91.508,135.888L 145.637,174.227 Z" />
                </Viewbox>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="star" Property="Fill" Value="Orange" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <ToggleButton Grid.Column="0" Tag="1" Cursor="Pen"  Template="{StaticResource ratingtemplate}" Click="ClickEventHandler" />
        <ToggleButton Grid.Column="1" Tag="2" Cursor="Pen"  Template="{StaticResource ratingtemplate}" Click="ClickEventHandler"/>
        <ToggleButton Grid.Column="2" Tag="3" Cursor="Pen"  Template="{StaticResource ratingtemplate}" Click="ClickEventHandler"/>
        <ToggleButton Grid.Column="3" Tag="4" Cursor="Pen"  Template="{StaticResource ratingtemplate}" Click="ClickEventHandler"/>
        <ToggleButton Grid.Column="4" Tag="5" Cursor="Pen"  Template="{StaticResource ratingtemplate}" Click="ClickEventHandler"/>
       
    </Grid>
</UserControl>


Xaml Application:

<Window x:Class="Testing_Rating.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:rating="clr-namespace:RatingControl"
   
        Title="MainWindow" Height="350" Width="525">
    <Window.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="#FF506450" Offset="0"/>
            <GradientStop Color="#FF200000" Offset="1"/>
        </LinearGradientBrush>
    </Window.Background>
    <Grid>
        <StackPanel Margin="50" Orientation="Horizontal">
            <TextBlock Foreground="RosyBrown" FontSize="16" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="10" FontFamily="Arial">Please Rate It</TextBlock>
            <rating:Rating Height="60" Width="100" VerticalAlignment="Center" Margin="0,80,0,79" />
        </StackPanel>
    </Grid>
</Window>





I hope from this article you can learn how to create a rating control in the Xaml .

3 comments:

  1. Hi

    I am using Visual Studio 2010 which has .net version 4.0. I cannot upgrade from this. As a result, I am unable to get
    FrameworkPropertyMetadata, FrameworkPropertyMetadataOptions in the cs
    ControlTemplate.Triggers, x:Type, Setter TargetName in the XAML.

    Please give the code for .net version 4. It will be a huge help. Thank you.

    ReplyDelete
  2. how can i data binding the value of this control ?

    ReplyDelete
    Replies
    1. Hi,
      I have the same question. How can i bind data?

      Delete