AutoDataTemplateBindingHookTest.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using Xunit;
  4. using ReactiveUI;
  5. using Avalonia.ReactiveUI;
  6. using Avalonia.UnitTests;
  7. using Avalonia.Controls;
  8. using Avalonia.Controls.Templates;
  9. using System.Collections.Generic;
  10. using System.Collections.ObjectModel;
  11. using System.Linq;
  12. using Avalonia.VisualTree;
  13. using Avalonia.Controls.Presenters;
  14. using Splat;
  15. using System.Threading.Tasks;
  16. using System;
  17. namespace Avalonia.ReactiveUI.UnitTests
  18. {
  19. public class AutoDataTemplateBindingHookTest
  20. {
  21. public class NestedViewModel : ReactiveObject { }
  22. public class NestedView : ReactiveUserControl<NestedViewModel> { }
  23. public class ExampleViewModel : ReactiveObject
  24. {
  25. public ObservableCollection<NestedViewModel> Items { get; } = new ObservableCollection<NestedViewModel>();
  26. }
  27. public class ExampleView : ReactiveUserControl<ExampleViewModel>
  28. {
  29. public ItemsControl List { get; } = new ItemsControl();
  30. public ExampleView()
  31. {
  32. Content = List;
  33. ViewModel = new ExampleViewModel();
  34. this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items);
  35. }
  36. }
  37. public AutoDataTemplateBindingHookTest()
  38. {
  39. Locator.CurrentMutable.RegisterConstant(new AutoDataTemplateBindingHook(), typeof(IPropertyBindingHook));
  40. Locator.CurrentMutable.RegisterConstant(new AvaloniaActivationForViewFetcher(), typeof(IActivationForViewFetcher));
  41. Locator.CurrentMutable.Register(() => new NestedView(), typeof(IViewFor<NestedViewModel>));
  42. }
  43. [Fact]
  44. public void Should_Apply_Data_Template_Binding_When_No_Template_Is_Set()
  45. {
  46. var view = new ExampleView();
  47. Assert.NotNull(view.List.ItemTemplate);
  48. }
  49. [Fact]
  50. public void Should_Use_View_Model_View_Host_As_Data_Template()
  51. {
  52. var view = new ExampleView();
  53. view.ViewModel.Items.Add(new NestedViewModel());
  54. view.List.Template = GetTemplate();
  55. view.List.ApplyTemplate();
  56. view.List.Presenter.ApplyTemplate();
  57. var child = view.List.Presenter.Panel.Children[0];
  58. var container = (ContentPresenter) child;
  59. container.UpdateChild();
  60. Assert.IsType<ViewModelViewHost>(container.Child);
  61. }
  62. [Fact]
  63. public void Should_Resolve_And_Embedd_Appropriate_View_Model()
  64. {
  65. var view = new ExampleView();
  66. var root = new TestRoot { Child = view };
  67. view.ViewModel.Items.Add(new NestedViewModel());
  68. view.List.Template = GetTemplate();
  69. view.List.ApplyTemplate();
  70. view.List.Presenter.ApplyTemplate();
  71. var child = view.List.Presenter.Panel.Children[0];
  72. var container = (ContentPresenter) child;
  73. container.UpdateChild();
  74. var host = (ViewModelViewHost) container.Child;
  75. Assert.IsType<NestedViewModel>(host.ViewModel);
  76. Assert.IsType<NestedViewModel>(host.DataContext);
  77. host.DataContext = "changed context";
  78. Assert.IsType<string>(host.ViewModel);
  79. Assert.IsType<string>(host.DataContext);
  80. }
  81. private FuncControlTemplate GetTemplate()
  82. {
  83. return new FuncControlTemplate<ItemsControl>((parent, scope) =>
  84. {
  85. return new Border
  86. {
  87. Background = new Media.SolidColorBrush(0xffffffff),
  88. Child = new ItemsPresenter
  89. {
  90. Name = "PART_ItemsPresenter",
  91. MemberSelector = parent.MemberSelector,
  92. [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
  93. }.RegisterInNameScope(scope)
  94. };
  95. });
  96. }
  97. }
  98. }