// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License (Ms-PL). // Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details. // All other rights reserved. using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Windows.Automation.Peers; using System.Windows.Controls.Primitives; using System.Windows.Input; namespace System.Windows.Controls { /// /// An item used in a rating control. /// /// Preview [TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)] [TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)] [TemplateVisualState(Name = VisualStates.StatePressed, GroupName = VisualStates.GroupCommon)] [TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)] [TemplateVisualState(Name = VisualStates.StateReadOnly, GroupName = VisualStates.GroupCommon)] [TemplateVisualState(Name = VisualStates.StateFocused, GroupName = VisualStates.GroupFocus)] [TemplateVisualState(Name = VisualStates.StateUnfocused, GroupName = VisualStates.GroupFocus)] [TemplateVisualState(Name = StateFilled, GroupName = GroupFill)] [TemplateVisualState(Name = StateEmpty, GroupName = GroupFill)] [TemplateVisualState(Name = StatePartial, GroupName = GroupFill)] public class RatingItem : ButtonBase, IUpdateVisualState { /// /// The state in which the item is filled. /// private const string StateFilled = "Filled"; /// /// The state in which the item is empty. /// private const string StateEmpty = "Empty"; /// /// The group that contains fill states. /// private const string GroupFill = "FillStates"; /// /// The state in which the item is partially filled. /// private const string StatePartial = "Partial"; /// /// The interaction helper used to get the common states working. /// private InteractionHelper _interactionHelper; #region public double DisplayValue /// /// A value indicating whether the actual value is being set. /// private bool _settingDisplayValue; /// /// Gets the actual value. /// public double DisplayValue { get { return (double)GetValue(DisplayValueProperty); } internal set { _settingDisplayValue = true; try { SetValue(DisplayValueProperty, value); } finally { _settingDisplayValue = false; } } } /// /// Identifies the DisplayValue dependency property. /// public static readonly DependencyProperty DisplayValueProperty = DependencyProperty.Register( "DisplayValue", typeof(double), typeof(RatingItem), new PropertyMetadata(0.0, OnDisplayValueChanged)); /// /// DisplayValueProperty property changed handler. /// /// RatingItem that changed its DisplayValue. /// Event arguments. private static void OnDisplayValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RatingItem source = (RatingItem)d; source.OnDisplayValueChanged((double)e.OldValue, (double)e.NewValue); } /// /// DisplayValueProperty property changed handler. /// /// The old value. /// The new value. private void OnDisplayValueChanged(double oldValue, double newValue) { if (!_settingDisplayValue) { _settingDisplayValue = true; this.DisplayValue = oldValue; throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Muchinfo.WPF.Controls.Properties.Resources.InvalidAttemptToChangeReadOnlyProperty, "DisplayValue")); } else { if (newValue <= 0.0) { VisualStates.GoToState(this, true, StateEmpty); } else if (newValue >= 1.0) { VisualStates.GoToState(this, true, StateFilled); } else { VisualStates.GoToState(this, true, StatePartial); } } } #endregion public double DisplayValue #region public bool IsReadOnly /// /// A value indicating whether the read only value is being set. /// private bool _settingIsReadOnly; /// /// Gets a value indicating whether the control is read-only. /// public bool IsReadOnly { get { return (bool)GetValue(IsReadOnlyProperty); } internal set { _settingIsReadOnly = true; try { SetValue(IsReadOnlyProperty, value); } finally { _settingIsReadOnly = false; } } } /// /// Identifies the IsReadOnly dependency property. /// public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof(bool), typeof(RatingItem), new PropertyMetadata(false, OnIsReadOnlyChanged)); /// /// IsReadOnlyProperty property changed handler. /// /// RatingItem that changed its IsReadOnly. /// Event arguments. private static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RatingItem source = (RatingItem)d; bool oldValue = (bool)e.OldValue; bool newValue = (bool)e.NewValue; source.OnIsReadOnlyChanged(oldValue, newValue); } /// /// IsReadOnlyProperty property changed handler. /// /// Old value. /// New value. protected virtual void OnIsReadOnlyChanged(bool oldValue, bool newValue) { if (!_settingIsReadOnly) { _settingIsReadOnly = true; this.IsReadOnly = oldValue; throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Muchinfo.WPF.Controls.Properties.Resources.InvalidAttemptToChangeReadOnlyProperty, "IsReadOnly")); } else { _interactionHelper.OnIsReadOnlyChanged(newValue); } } #endregion public bool IsReadOnly /// /// Gets or sets the parent rating of this rating item. /// internal Rating ParentRating { get; set; } #region public double Value /// /// Gets or sets the value property. /// [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "Value is the logical name for this property.")] internal double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } /// /// Identifies the Value dependency property. /// internal static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(double), typeof(RatingItem), new PropertyMetadata(0.0)); /// /// Selects a value and raises the value selected event. /// internal void SelectValue() { if (!this.IsReadOnly) { this.Value = 1.0; OnClick(); } } #endregion public double Value #if !SILVERLIGHT /// /// Initializes the static members of the ColumnDataPoint class. /// static RatingItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(RatingItem), new FrameworkPropertyMetadata(typeof(RatingItem))); } #endif /// /// Initializes a new instance of the RatingItem class. /// public RatingItem() { #if SILVERLIGHT this.DefaultStyleKey = typeof(RatingItem); #endif _interactionHelper = new InteractionHelper(this); } /// /// Provides handling for the RatingItem's MouseLeftButtonDown event. /// /// Event arguments. protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { if (_interactionHelper.AllowMouseLeftButtonDown(e)) { _interactionHelper.OnMouseLeftButtonDownBase(); } base.OnMouseLeftButtonDown(e); } /// /// Provides handling for the RatingItem's MouseLeftButtonUp event. /// /// Event arguments. protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { if (_interactionHelper.AllowMouseLeftButtonUp(e)) { _interactionHelper.OnMouseLeftButtonUpBase(); } base.OnMouseLeftButtonUp(e); } /// /// This method is invoked when the mouse enters the rating item. /// /// Information about the event. protected override void OnMouseEnter(MouseEventArgs e) { if (_interactionHelper.AllowMouseEnter(e)) { _interactionHelper.UpdateVisualStateBase(true); } base.OnMouseEnter(e); } /// /// This method is invoked when the mouse leaves the rating item. /// /// Information about the event. protected override void OnMouseLeave(MouseEventArgs e) { if (_interactionHelper.AllowMouseLeave(e)) { _interactionHelper.UpdateVisualStateBase(true); } base.OnMouseLeave(e); } /// /// Sets the value to 1.0 when clicked. /// protected override void OnClick() { base.OnClick(); } /// /// Updates the visual state. /// /// A value indicating whether to use /// transitions. void IUpdateVisualState.UpdateVisualState(bool useTransitions) { _interactionHelper.UpdateVisualStateBase(useTransitions); } /// /// Returns a AccordionItemAutomationPeer for use by the Silverlight /// automation infrastructure. /// /// A AccordionItemAutomationPeer object for the AccordionItem. protected override AutomationPeer OnCreateAutomationPeer() { return new RatingItemAutomationPeer(this); } } }