Browse Source

Use direct PPs for SelectedIndex/Items.

Steven Kirk 10 years ago
parent
commit
cbfbc52803

+ 9 - 1
src/Perspex.Base/PerspexObject.cs

@@ -773,13 +773,21 @@ namespace Perspex
         /// <param name="property">The property.</param>
         /// <param name="field">The backing field.</param>
         /// <param name="value">The value.</param>
-        protected void SetAndRaise<T>(PerspexProperty<T> property, ref T field, T value)
+        /// <returns>
+        /// True if the value changed, otherwise false.
+        /// </returns>
+        protected bool SetAndRaise<T>(PerspexProperty<T> property, ref T field, T value)
         {
             if (!object.Equals(field, value))
             {
                 var old = field;
                 field = value;
                 RaisePropertyChanged(property, old, value, BindingPriority.LocalValue);
+                return true;
+            }
+            else
+            {
+                return false;
             }
         }
 

+ 28 - 31
src/Perspex.Controls/ItemsControl.cs

@@ -47,7 +47,7 @@ namespace Perspex.Controls
         public static readonly PerspexProperty<IMemberSelector> MemberSelectorProperty =
             PerspexProperty.Register<ItemsControl, IMemberSelector>(nameof(MemberSelector));
 
-        private IEnumerable _items;
+        private IEnumerable _items = new PerspexList<object>();
         private IItemContainerGenerator _itemContainerGenerator;
 
         /// <summary>
@@ -64,6 +64,7 @@ namespace Perspex.Controls
         public ItemsControl()
         {
             Classes.Add(":empty");
+            SubscribeToItems(_items);
         }
 
         /// <summary>
@@ -87,20 +88,8 @@ namespace Perspex.Controls
         /// </summary>
         public IEnumerable Items
         {
-            get
-            {
-                if (_items == null)
-                {
-                    _items = new PerspexList<object>();
-                }
-
-                return _items;
-            }
-
-            set
-            {
-                SetAndRaise(ItemsProperty, ref _items, value);
-            }
+            get { return _items; }
+            set { SetAndRaise(ItemsProperty, ref _items, value); }
         }
 
         /// <summary>
@@ -175,22 +164,7 @@ namespace Perspex.Controls
             }
 
             var newValue = e.NewValue as IEnumerable;
-
-            if (newValue == null || newValue.Count() == 0)
-            {
-                Classes.Add(":empty");
-            }
-            else
-            {
-                Classes.Remove(":empty");
-            }
-
-            incc = newValue as INotifyCollectionChanged;
-
-            if (incc != null)
-            {
-                incc.CollectionChanged += ItemsCollectionChanged;
-            }
+            SubscribeToItems(newValue);
         }
 
         /// <summary>
@@ -212,5 +186,28 @@ namespace Perspex.Controls
                 Classes.Remove(":empty");
             }
         }
+
+        /// <summary>
+        /// Subscribes to an <see cref="Items"/> collection.
+        /// </summary>
+        /// <param name="items"></param>
+        private void SubscribeToItems(IEnumerable items)
+        {
+            if (items == null || items.Count() == 0)
+            {
+                Classes.Add(":empty");
+            }
+            else
+            {
+                Classes.Remove(":empty");
+            }
+
+            var incc = items as INotifyCollectionChanged;
+
+            if (incc != null)
+            {
+                incc.CollectionChanged += ItemsCollectionChanged;
+            }
+        }
     }
 }

+ 7 - 4
src/Perspex.Controls/Presenters/DeckPresenter.cs

@@ -41,7 +41,9 @@ namespace Perspex.Controls.Presenters
         /// Defines the <see cref="SelectedIndex"/> property.
         /// </summary>
         public static readonly PerspexProperty<int> SelectedIndexProperty =
-            SelectingItemsControl.SelectedIndexProperty.AddOwner<DeckPresenter>();
+            SelectingItemsControl.SelectedIndexProperty.AddOwner<DeckPresenter>(
+                o => o.SelectedIndex,
+                (o, v) => o.SelectedIndex = v);
 
         /// <summary>
         /// Defines the <see cref="Transition"/> property.
@@ -50,6 +52,7 @@ namespace Perspex.Controls.Presenters
             Deck.TransitionProperty.AddOwner<DeckPresenter>();
 
         private IEnumerable _items;
+        private int _selectedIndex = -1;
         private bool _createdPanel;
         private IItemContainerGenerator _generator;
 
@@ -121,8 +124,8 @@ namespace Perspex.Controls.Presenters
         /// </summary>
         public int SelectedIndex
         {
-            get { return GetValue(SelectedIndexProperty); }
-            set { SetValue(SelectedIndexProperty, value); }
+            get { return _selectedIndex; }
+            set { SetAndRaise(SelectedIndexProperty, ref _selectedIndex, value); }
         }
 
         /// <summary>
@@ -204,7 +207,7 @@ namespace Perspex.Controls.Presenters
                 }
             }
 
-            if (Transition != null)
+            if (Transition != null && (from != null || to != null))
             {
                 await Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex);
             }

+ 29 - 33
src/Perspex.Controls/Primitives/SelectingItemsControl.cs

@@ -31,18 +31,19 @@ namespace Perspex.Controls.Primitives
         /// Defines the <see cref="SelectedIndex"/> property.
         /// </summary>
         public static readonly PerspexProperty<int> SelectedIndexProperty =
-            PerspexProperty.Register<SelectingItemsControl, int>(
+            PerspexProperty.RegisterDirect<SelectingItemsControl, int>(
                 nameof(SelectedIndex),
-                defaultValue: -1,
-                validate: ValidateSelectedIndex);
+                o => o.SelectedIndex,
+                (o, v) => o.SelectedIndex = v);
 
         /// <summary>
         /// Defines the <see cref="SelectedItem"/> property.
         /// </summary>
         public static readonly PerspexProperty<object> SelectedItemProperty =
-            PerspexProperty.Register<SelectingItemsControl, object>(
+            PerspexProperty.RegisterDirect<SelectingItemsControl, object>(
                 nameof(SelectedItem),
-                validate: ValidateSelectedItem);
+                o => o.SelectedItem,
+                (o, v) => o.SelectedItem = v);
 
         /// <summary>
         /// Event that should be raised by items that implement <see cref="ISelectable"/> to
@@ -52,6 +53,9 @@ namespace Perspex.Controls.Primitives
         public static readonly RoutedEvent<RoutedEventArgs> IsSelectedChangedEvent =
             RoutedEvent.Register<SelectingItemsControl, RoutedEventArgs>("IsSelectedChanged", RoutingStrategies.Bubble);
 
+        private int _selectedIndex = -1;
+        private object _selectedItem;
+
         /// <summary>
         /// Initializes static members of the <see cref="SelectingItemsControl"/> class.
         /// </summary>
@@ -85,8 +89,16 @@ namespace Perspex.Controls.Primitives
         /// </summary>
         public int SelectedIndex
         {
-            get { return GetValue(SelectedIndexProperty); }
-            set { SetValue(SelectedIndexProperty, value); }
+            get
+            {
+                return _selectedIndex;
+            }
+
+            set
+            {
+                value = (value >= 0 && value < Items?.Cast<object>().Count()) ? value : -1;
+                SetAndRaise(SelectedIndexProperty, ref _selectedIndex, value);
+            }
         }
 
         /// <summary>
@@ -94,8 +106,16 @@ namespace Perspex.Controls.Primitives
         /// </summary>
         public object SelectedItem
         {
-            get { return GetValue(SelectedItemProperty); }
-            set { SetValue(SelectedItemProperty, value); }
+            get
+            {
+                return _selectedItem;
+            }
+
+            set
+            {
+                value = Items?.Cast<object>().Contains(value) == true ? value : null;
+                SetAndRaise(SelectedItemProperty, ref _selectedItem, value);
+            }
         }
 
         /// <inheritdoc/>
@@ -234,30 +254,6 @@ namespace Perspex.Controls.Primitives
             }
         }
 
-        /// <summary>
-        /// Coerces the <see cref="SelectedIndex"/> property.
-        /// </summary>
-        /// <param name="sender">The object with the property.</param>
-        /// <param name="index">The proposed value of the property.</param>
-        /// <returns>The final value of the property.</returns>
-        private static int ValidateSelectedIndex(SelectingItemsControl sender, int index)
-        {
-            var items = sender.Items;
-            return (index >= 0 && index < items?.Cast<object>().Count()) ? index : -1;
-        }
-
-        /// <summary>
-        /// Coerces the <see cref="SelectedItem"/> property.
-        /// </summary>
-        /// <param name="sender">The object with the property.</param>
-        /// <param name="item">The proposed value of the property.</param>
-        /// <returns>The final value of the property.</returns>
-        private static object ValidateSelectedItem(SelectingItemsControl sender, object item)
-        {
-            var items = sender.Items;
-            return items?.Cast<object>().Contains(item) == true ? item : null;
-        }
-
         /// <summary>
         /// Called when new containers are initialized by the <see cref="ItemContainerGenerator"/>.
         /// </summary>

+ 1 - 0
tests/Perspex.Controls.UnitTests/Primitives/TabStripTests.cs

@@ -33,6 +33,7 @@ namespace Perspex.Controls.UnitTests.Primitives
 
             target.ApplyTemplate();
 
+            Assert.Equal(0, target.SelectedIndex);
             Assert.Equal(target.Items.Cast<TabItem>().First(), target.SelectedItem);
             Assert.Equal(target.Items.Cast<TabItem>().First(), target.SelectedTab);
         }