csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
831 lines
23 KiB
831 lines
23 KiB
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using Avalonia.Collections;
|
|
using Avalonia.Controls.Presenters;
|
|
using Avalonia.Controls.Primitives;
|
|
using Avalonia.Controls.Templates;
|
|
using Avalonia.Data;
|
|
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Markup.Data;
|
|
using Avalonia.UnitTests;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Avalonia.Controls.UnitTests.Primitives
|
|
{
|
|
public class SelectingItemsControlTests
|
|
{
|
|
private MouseTestHelper _helper = new MouseTestHelper();
|
|
|
|
[Fact]
|
|
public void SelectedIndex_Should_Initially_Be_Minus_1()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Item_IsSelected_Should_Initially_Be_False()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.False(items[1].IsSelected);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedItem_Should_Set_Item_IsSelected_True()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.True(items[1].IsSelected);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedItem_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.SelectedItem = items[1];
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.True(items[1].IsSelected);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedIndex_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.SelectedIndex = 1;
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.True(items[1].IsSelected);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedItem_Should_Set_SelectedIndex()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectedIndex_Item_Is_Updated_As_Items_Removed_When_Last_Item_Is_Selected()
|
|
{
|
|
var items = new ObservableCollection<string>
|
|
{
|
|
"Foo",
|
|
"Bar",
|
|
"FooBar"
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedItem = items[2];
|
|
|
|
Assert.Equal(items[2], target.SelectedItem);
|
|
Assert.Equal(2, target.SelectedIndex);
|
|
|
|
items.RemoveAt(0);
|
|
|
|
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 SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
|
|
target.SelectedItem = new Item();
|
|
|
|
Assert.Null(target.SelectedItem);
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedIndex_Should_Set_SelectedItem()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 1;
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedIndex_Out_Of_Bounds_Should_Clear_Selection()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 2;
|
|
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedItem_To_Non_Existent_Item_Should_Clear_Selection()
|
|
{
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedItem = new Item();
|
|
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
Assert.Null(target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Adding_Selected_Item_Should_Update_Selection()
|
|
{
|
|
var items = new AvaloniaList<Item>(new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
});
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
items.Add(new Item { IsSelected = true });
|
|
|
|
Assert.Equal(2, target.SelectedIndex);
|
|
Assert.Equal(items[2], target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_Items_To_Null_Should_Clear_Selection()
|
|
{
|
|
var items = new AvaloniaList<Item>
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 1;
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
|
|
target.Items = null;
|
|
|
|
Assert.Null(target.SelectedItem);
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Removing_Selected_Item_Should_Clear_Selection()
|
|
{
|
|
var items = new AvaloniaList<Item>
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 1;
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
|
|
items.RemoveAt(1);
|
|
|
|
Assert.Null(target.SelectedItem);
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Moving_Selected_Item_Should_Update_Selection()
|
|
{
|
|
var items = new AvaloniaList<Item>
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 0;
|
|
|
|
Assert.Equal(items[0], target.SelectedItem);
|
|
Assert.Equal(0, target.SelectedIndex);
|
|
|
|
items.Move(0, 1);
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Resetting_Items_Collection_Should_Clear_Selection()
|
|
{
|
|
// Need to use ObservableCollection here as AvaloniaList signals a Clear as an
|
|
// add + remove.
|
|
var items = new ObservableCollection<Item>
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedIndex = 1;
|
|
|
|
Assert.Equal(items[1], target.SelectedItem);
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
|
|
items.Clear();
|
|
|
|
Assert.Null(target.SelectedItem);
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.True(items[1].IsSelected);
|
|
|
|
items[0].IsSelected = true;
|
|
items[0].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
|
|
|
|
Assert.Equal(0, target.SelectedIndex);
|
|
Assert.Equal(items[0], target.SelectedItem);
|
|
Assert.True(items[0].IsSelected);
|
|
Assert.False(items[1].IsSelected);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clearing_IsSelected_And_Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
Assert.False(items[0].IsSelected);
|
|
Assert.True(items[1].IsSelected);
|
|
|
|
items[1].IsSelected = false;
|
|
items[1].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
|
|
|
|
Assert.Equal(-1, target.SelectedIndex);
|
|
Assert.Null(target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Raising_IsSelectedChanged_On_Someone_Elses_Item_Should_Not_Update_Selection()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.SelectedItem = items[1];
|
|
|
|
var notChild = new Item
|
|
{
|
|
IsSelected = true,
|
|
};
|
|
|
|
target.RaiseEvent(new RoutedEventArgs
|
|
{
|
|
RoutedEvent = SelectingItemsControl.IsSelectedChangedEvent,
|
|
Source = notChild,
|
|
});
|
|
|
|
Assert.Equal(target.SelectedItem, items[1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedIndex_Should_Raise_SelectionChanged_Event()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
};
|
|
|
|
var called = false;
|
|
|
|
target.SelectionChanged += (s, e) =>
|
|
{
|
|
Assert.Same(items[1], e.AddedItems.Cast<object>().Single());
|
|
Assert.Empty(e.RemovedItems);
|
|
called = true;
|
|
};
|
|
|
|
target.SelectedIndex = 1;
|
|
|
|
Assert.True(called);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clearing_SelectedIndex_Should_Raise_SelectionChanged_Event()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = items,
|
|
Template = Template(),
|
|
SelectedIndex = 1,
|
|
};
|
|
|
|
var called = false;
|
|
|
|
target.SelectionChanged += (s, e) =>
|
|
{
|
|
Assert.Same(items[1], e.RemovedItems.Cast<object>().Single());
|
|
Assert.Empty(e.AddedItems);
|
|
called = true;
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
target.SelectedIndex = -1;
|
|
|
|
Assert.True(called);
|
|
}
|
|
|
|
[Fact]
|
|
public void Order_Of_Setting_Items_And_SelectedIndex_During_Initialization_Should_Not_Matter()
|
|
{
|
|
var items = new[] { "Foo", "Bar" };
|
|
var target = new SelectingItemsControl();
|
|
|
|
((ISupportInitialize)target).BeginInit();
|
|
target.SelectedIndex = 1;
|
|
target.Items = items;
|
|
((ISupportInitialize)target).EndInit();
|
|
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
Assert.Equal("Bar", target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Order_Of_Setting_Items_And_SelectedItem_During_Initialization_Should_Not_Matter()
|
|
{
|
|
var items = new[] { "Foo", "Bar" };
|
|
var target = new SelectingItemsControl();
|
|
|
|
((ISupportInitialize)target).BeginInit();
|
|
target.SelectedItem = "Bar";
|
|
target.Items = items;
|
|
((ISupportInitialize)target).EndInit();
|
|
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
Assert.Equal("Bar", target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Changing_DataContext_Should_Not_Clear_Nested_ViewModel_SelectedItem()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var vm = new MasterViewModel
|
|
{
|
|
Child = new ChildViewModel
|
|
{
|
|
Items = items,
|
|
SelectedItem = items[1],
|
|
}
|
|
};
|
|
|
|
var target = new SelectingItemsControl { DataContext = vm };
|
|
var itemsBinding = new Binding("Child.Items");
|
|
var selectedBinding = new Binding("Child.SelectedItem");
|
|
|
|
target.Bind(SelectingItemsControl.ItemsProperty, itemsBinding);
|
|
target.Bind(SelectingItemsControl.SelectedItemProperty, selectedBinding);
|
|
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
|
|
|
|
items = new[]
|
|
{
|
|
new Item { Value = "Item1" },
|
|
new Item { Value = "Item2" },
|
|
new Item { Value = "Item3" },
|
|
};
|
|
|
|
vm = new MasterViewModel
|
|
{
|
|
Child = new ChildViewModel
|
|
{
|
|
Items = items,
|
|
SelectedItem = items[2],
|
|
}
|
|
};
|
|
|
|
target.DataContext = vm;
|
|
|
|
Assert.Equal(2, target.SelectedIndex);
|
|
Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Nested_ListBox_Does_Not_Change_Parent_SelectedIndex()
|
|
{
|
|
SelectingItemsControl nested;
|
|
|
|
var root = new SelectingItemsControl
|
|
{
|
|
Template = Template(),
|
|
Items = new IControl[]
|
|
{
|
|
new Border(),
|
|
nested = new ListBox
|
|
{
|
|
Template = Template(),
|
|
Items = new[] { "foo", "bar" },
|
|
SelectedIndex = 1,
|
|
}
|
|
},
|
|
SelectedIndex = 0,
|
|
};
|
|
|
|
root.ApplyTemplate();
|
|
root.Presenter.ApplyTemplate();
|
|
nested.ApplyTemplate();
|
|
nested.Presenter.ApplyTemplate();
|
|
|
|
Assert.Equal(0, root.SelectedIndex);
|
|
Assert.Equal(1, nested.SelectedIndex);
|
|
|
|
nested.SelectedIndex = 0;
|
|
|
|
Assert.Equal(0, root.SelectedIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Setting_SelectedItem_With_Pointer_Should_Set_TabOnceActiveElement()
|
|
{
|
|
var target = new ListBox
|
|
{
|
|
Template = Template(),
|
|
Items = new[] { "Foo", "Bar", "Baz " },
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
_helper.Down((Interactive)target.Presenter.Panel.Children[1]);
|
|
|
|
var panel = target.Presenter.Panel;
|
|
|
|
Assert.Equal(
|
|
KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel),
|
|
panel.Children[1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Removing_SelectedItem_Should_Clear_TabOnceActiveElement()
|
|
{
|
|
var items = new ObservableCollection<string>(new[] { "Foo", "Bar", "Baz " });
|
|
|
|
var target = new ListBox
|
|
{
|
|
Template = Template(),
|
|
Items = items,
|
|
};
|
|
|
|
target.ApplyTemplate();
|
|
target.Presenter.ApplyTemplate();
|
|
|
|
_helper.Down(target.Presenter.Panel.Children[1]);
|
|
|
|
items.RemoveAt(1);
|
|
|
|
var panel = target.Presenter.Panel;
|
|
|
|
Assert.Null(KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel));
|
|
}
|
|
|
|
[Fact]
|
|
public void Resetting_Items_Collection_Should_Retain_Selection()
|
|
{
|
|
var itemsMock = new Mock<List<string>>();
|
|
var itemsMockAsINCC = itemsMock.As<INotifyCollectionChanged>();
|
|
|
|
itemsMock.Object.AddRange(new[] { "Foo", "Bar", "Baz" });
|
|
var target = new SelectingItemsControl
|
|
{
|
|
Items = itemsMock.Object
|
|
};
|
|
|
|
target.SelectedIndex = 1;
|
|
|
|
itemsMockAsINCC.Raise(e => e.CollectionChanged += null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
|
|
Assert.True(target.SelectedIndex == 1);
|
|
}
|
|
|
|
[Fact]
|
|
public void Binding_With_DelayedBinding_And_Initialization_Where_DataContext_Is_Root_Works()
|
|
{
|
|
// Test for #1932.
|
|
var root = new RootWithItems();
|
|
|
|
root.BeginInit();
|
|
root.DataContext = root;
|
|
|
|
var target = new ListBox();
|
|
target.BeginInit();
|
|
root.Child = target;
|
|
|
|
DelayedBinding.Add(target, ItemsControl.ItemsProperty, new Binding(nameof(RootWithItems.Items)));
|
|
DelayedBinding.Add(target, ListBox.SelectedItemProperty, new Binding(nameof(RootWithItems.Selected)));
|
|
target.EndInit();
|
|
root.EndInit();
|
|
|
|
Assert.Equal("b", target.SelectedItem);
|
|
}
|
|
|
|
[Fact]
|
|
public void Mode_For_SelectedIndex_Is_TwoWay_By_Default()
|
|
{
|
|
var items = new[]
|
|
{
|
|
new Item(),
|
|
new Item(),
|
|
new Item(),
|
|
};
|
|
|
|
var vm = new MasterViewModel
|
|
{
|
|
Child = new ChildViewModel
|
|
{
|
|
Items = items,
|
|
SelectedIndex = 1,
|
|
}
|
|
};
|
|
|
|
var target = new SelectingItemsControl { DataContext = vm };
|
|
var itemsBinding = new Binding("Child.Items");
|
|
var selectedIndBinding = new Binding("Child.SelectedIndex");
|
|
|
|
target.Bind(SelectingItemsControl.ItemsProperty, itemsBinding);
|
|
target.Bind(SelectingItemsControl.SelectedIndexProperty, selectedIndBinding);
|
|
|
|
Assert.Equal(1, target.SelectedIndex);
|
|
|
|
target.SelectedIndex = 2;
|
|
|
|
Assert.Equal(2, target.SelectedIndex);
|
|
Assert.Equal(2, vm.Child.SelectedIndex);
|
|
}
|
|
|
|
private FuncControlTemplate Template()
|
|
{
|
|
return new FuncControlTemplate<SelectingItemsControl>(control =>
|
|
new ItemsPresenter
|
|
{
|
|
Name = "itemsPresenter",
|
|
[~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
|
|
[~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
|
|
});
|
|
}
|
|
|
|
private class Item : Control, ISelectable
|
|
{
|
|
public string Value { get; set; }
|
|
public bool IsSelected { get; set; }
|
|
}
|
|
|
|
private class MasterViewModel : NotifyingBase
|
|
{
|
|
private ChildViewModel _child;
|
|
|
|
public ChildViewModel Child
|
|
{
|
|
get { return _child; }
|
|
set
|
|
{
|
|
_child = value;
|
|
RaisePropertyChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private class ChildViewModel : NotifyingBase
|
|
{
|
|
public IList<Item> Items { get; set; }
|
|
public Item SelectedItem { get; set; }
|
|
public int SelectedIndex { get; set; }
|
|
}
|
|
|
|
private class RootWithItems : TestRoot
|
|
{
|
|
public List<string> Items { get; set; } = new List<string>() { "a", "b", "c", "d", "e" };
|
|
public string Selected { get; set; } = "b";
|
|
}
|
|
}
|
|
}
|
|
|