In addition to handling events, it is important to commit to your developer audience. Because of this, you also must decide which functionality and properties you will allow other developers to access. In the case of the rating control, providing a hook into the rating that the user selected seems beneficial. Because of this, provide a rating property that other developers can use to access the control:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
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 CustomControlLibrary
{
public partial class RatingUserControl :
System.Windows.Controls.UserControl
{
public RatingUserControl()
{
InitializeComponent();
}
private int rating = 0;
public int Rating
{
get { return rating; }
set { rating = value;}
}
public void OnMouseLeftButtonUp(object sender, RoutedEventArgs e)
{
string selectedEllipseName = ((Ellipse)(e.Source)).Name;
string selectedRating =
selectedEllipseName.Substring(selectedEllipseName.Length-1);
rating = Convert.ToInt32(selectedRating);
}
public void OnMouseEnter(object sender, RoutedEventArgs e)
{
string selectedEllipseName = ((Ellipse)(e.Source)).Name;
bool found = false;
foreach (UIElement child in EllipsesStackPanel.Children)
{
if (found == true)
ellipse.Style = (Style)(this.Resources["UnselectedStyle"]);
else
ellipse.Style = (Style)(this.Resources["SelectedStyle"]);
if (ellipse.Name == selectedEllipseName)
found = true;
}
}
public void OnMouseLeave(object sender, RoutedEventArgs e)
{
string previousRating = "Ellipse" + rating;
bool found = false;
foreach (UIElement child in EllipsesStackPanel.Children)
{
Ellipse ellipse = (Ellipse)(child);
if ((found == true) || (rating == 0))
ellipse.Style = (Style)(this.Resources["UnselectedStyle"]);
else
ellipse.Style = (Style)(this.Resources["SelectedStyle"]);
if (ellipse.Name == previousRating)
found = true;
}
}
}
}
Much like user controls from previous .NET UI components, you have the ability to implement a code-behind class; this enables you to separate the procedural code from the user experience implementation. The custom class derives from System.Windows.Controls.UserControl. The rest of the implementation will be familiar to .NET developers. This familiarity makes WPF development great!
Testing
To test the custom control, you need to create a wrapper application. The purpose of the wrapper application is to test the complete control conclusively, including the following:
- User experience: XAMLPad is a great tool for testing the layout and appearance of controls. However, it lacks the ability to test user interaction because the event handling is implemented within the code-behind.
- Data binding: It is possible that through the programmatic handles (the methods and properties) another developer may render the control differently based on data from a data source. For instance, you may want to display the rating the user previously entered.
The Custom Controls of Your Dreams
The source code for this practical example provides the framework for developing the custom controls of your dreams, and in the case of the example, the rating control of your dreams. With the combination of the powerful user experience provided by WPF and the productivity of reusing custom controls, it has become easier than ever to fulfill your end users' application desires.
Acknowledgement
This article was edited by Rachel Wireman.
About the Author
 |
Chad Campbell (MCSD, MCTS) is a solutions developer for mid- to large-sized organizations. He is a thought leader with Crowe Chizek in Indianapolis, Indiana. Chad specializes in Web-based solutions, Reach him at cacampbell@crowechizek.com. |
* This article originally appeared on CodeGuru.