diff --git a/Perspex.Controls/Primitives/SelectingItemsControl.cs b/Perspex.Controls/Primitives/SelectingItemsControl.cs index b73af7712c..de011299c0 100644 --- a/Perspex.Controls/Primitives/SelectingItemsControl.cs +++ b/Perspex.Controls/Primitives/SelectingItemsControl.cs @@ -18,7 +18,7 @@ namespace Perspex.Controls.Primitives PerspexProperty.Register("SelectedIndex", coerce: CoerceSelectedIndex); public static readonly PerspexProperty SelectedItemProperty = - PerspexProperty.Register("SelectedItem"); + PerspexProperty.Register("SelectedItem", coerce: CoerceSelectedItem); static SelectingItemsControl() { @@ -30,7 +30,16 @@ namespace Perspex.Controls.Primitives if (control != null) { - control.SelectedItem = control.Items.ElementAt((int)x.NewValue); + var index = (int)x.NewValue; + + if (index == -1) + { + control.SelectedItem = null; + } + else + { + control.SelectedItem = control.Items.ElementAt((int)x.NewValue); + } } }); @@ -156,8 +165,32 @@ namespace Perspex.Controls.Primitives } else if (value > -1) { - var count = control.Items.Count(); - return Math.Min(value, count - 1); + var items = control.Items; + + if (items != null) + { + var count = items.Count(); + return Math.Min(value, count - 1); + } + else + { + return -1; + } + } + } + + return value; + } + + private static object CoerceSelectedItem(PerspexObject o, object value) + { + var control = o as SelectingItemsControl; + + if (control != null) + { + if (value != null && (control.Items == null || control.Items.IndexOf(value) == -1)) + { + return -1; } } @@ -189,7 +222,12 @@ namespace Perspex.Controls.Primitives } else { - this.SelectedIndex = this.Items.IndexOf(selected); + var items = this.Items; + + if (items != null) + { + this.SelectedIndex = items.IndexOf(selected); + } } } } diff --git a/Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index 3e9e2a3031..01286445c6 100644 --- a/Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -25,8 +25,11 @@ namespace Perspex.Controls.Primitives.UnitTests var target = new Target { Items = items, + Template = this.Template(), }; + target.ApplyTemplate(); + Assert.False(items[0].IsSelected); Assert.False(items[1].IsSelected); } @@ -43,9 +46,9 @@ namespace Perspex.Controls.Primitives.UnitTests var target = new Target { Items = items, + Template = this.Template(), }; - target.Template = this.Template(); target.ApplyTemplate(); target.SelectedItem = items[1]; @@ -65,15 +68,43 @@ namespace Perspex.Controls.Primitives.UnitTests var target = new Target { Items = items, + Template = this.Template(), }; - target.Template = this.Template(); target.ApplyTemplate(); target.SelectedItem = items[1]; + Assert.Equal(items[1], target.SelectedItem); Assert.Equal(1, target.SelectedIndex); } + [Fact] + public void Setting_SelectedItem_To_Not_Present_Item_Should_Clear_Selection() + { + var items = new[] + { + new Item(), + new Item(), + }; + + var target = new Target + { + Items = items, + Template = this.Template(), + }; + + target.ApplyTemplate(); + target.SelectedItem = items[1]; + + Assert.Equal(items[1], target.SelectedItem); + Assert.Equal(1, target.SelectedIndex); + + target.SelectedItem = new Item(); + + Assert.Equal(null, target.SelectedItem); + Assert.Equal(-1, target.SelectedIndex); + } + [Fact] public void Setting_SelectedIndex_Should_Set_SelectedItem() { @@ -86,9 +117,9 @@ namespace Perspex.Controls.Primitives.UnitTests var target = new Target { Items = items, + Template = this.Template(), }; - target.Template = this.Template(); target.ApplyTemplate(); target.SelectedIndex = 1; @@ -107,15 +138,41 @@ namespace Perspex.Controls.Primitives.UnitTests var target = new Target { Items = items, + Template = this.Template(), }; - target.Template = this.Template(); target.ApplyTemplate(); target.SelectedIndex = 2; Assert.Equal(1, target.SelectedIndex); } + [Fact] + public void Setting_SelectedIndex_With_No_Items_Should_Not_Throw_Exception() + { + var target = new Target + { + Template = this.Template(), + }; + + target.ApplyTemplate(); + target.SelectedIndex = 2; + + Assert.Equal(-1, target.SelectedIndex); + } + + [Fact] + public void Setting_SelectedItem_With_No_Items_Should_Not_Throw_Exception() + { + var target = new Target + { + Template = this.Template(), + }; + + target.ApplyTemplate(); + target.SelectedItem = new Item(); + } + [Fact] public void PointerPressed_Event_Should_Be_Handled() {