AutoDataTemplateBindingHookTest.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using Xunit;
  2. using ReactiveUI;
  3. using Avalonia.ReactiveUI;
  4. using Avalonia.UnitTests;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.Templates;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Linq;
  10. using Avalonia.VisualTree;
  11. using Avalonia.Controls.Presenters;
  12. using Splat;
  13. using System.Threading.Tasks;
  14. using System;
  15. namespace Avalonia.ReactiveUI.UnitTests
  16. {
  17. public class AutoDataTemplateBindingHookTest
  18. {
  19. public class NestedViewModel : ReactiveObject { }
  20. public class NestedView : ReactiveUserControl<NestedViewModel> { }
  21. public class ExampleViewModel : ReactiveObject
  22. {
  23. public ObservableCollection<NestedViewModel> Items { get; } = new ObservableCollection<NestedViewModel>();
  24. }
  25. public class ExampleView : ReactiveUserControl<ExampleViewModel>
  26. {
  27. public ItemsControl List { get; } = new ItemsControl
  28. {
  29. Template = GetTemplate()
  30. };
  31. public ExampleView(Action<ItemsControl> adjustItemsControl = null)
  32. {
  33. adjustItemsControl?.Invoke(List);
  34. List.ApplyTemplate();
  35. List.Presenter.ApplyTemplate();
  36. Content = List;
  37. ViewModel = new ExampleViewModel();
  38. this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items);
  39. }
  40. }
  41. public AutoDataTemplateBindingHookTest()
  42. {
  43. Locator.CurrentMutable.RegisterConstant(new AutoDataTemplateBindingHook(), typeof(IPropertyBindingHook));
  44. Locator.CurrentMutable.RegisterConstant(new AvaloniaActivationForViewFetcher(), typeof(IActivationForViewFetcher));
  45. Locator.CurrentMutable.Register(() => new NestedView(), typeof(IViewFor<NestedViewModel>));
  46. }
  47. [Fact]
  48. public void Should_Apply_Data_Template_Binding_When_No_Template_Is_Set()
  49. {
  50. var view = new ExampleView();
  51. Assert.NotNull(view.List.ItemTemplate);
  52. Assert.IsType<FuncDataTemplate<object>>(view.List.ItemTemplate);
  53. }
  54. [Fact]
  55. public void Should_Not_Override_Data_Template_Binding_When_Item_Template_Is_Set()
  56. {
  57. var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate());
  58. Assert.NotNull(view.List.ItemTemplate);
  59. Assert.IsType<FuncDataTemplate<TextBlock>>(view.List.ItemTemplate);
  60. }
  61. [Fact]
  62. public void Should_Use_View_Model_View_Host_As_Data_Template()
  63. {
  64. var view = new ExampleView();
  65. view.ViewModel.Items.Add(new NestedViewModel());
  66. var child = view.List.Presenter.Panel.Children[0];
  67. var container = (ContentPresenter) child;
  68. container.UpdateChild();
  69. Assert.IsType<ViewModelViewHost>(container.Child);
  70. }
  71. [Fact]
  72. public void Should_Not_Use_View_Model_View_Host_When_Item_Template_Is_Set()
  73. {
  74. var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate());
  75. view.ViewModel.Items.Add(new NestedViewModel());
  76. var child = view.List.Presenter.Panel.Children[0];
  77. var container = (ContentPresenter) child;
  78. container.UpdateChild();
  79. Assert.IsType<TextBlock>(container.Child);
  80. }
  81. [Fact]
  82. public void Should_Not_Use_View_Model_View_Host_When_Data_Templates_Are_Not_Empty()
  83. {
  84. var view = new ExampleView(control => control.DataTemplates.Add(GetItemTemplate()));
  85. view.ViewModel.Items.Add(new NestedViewModel());
  86. var child = view.List.Presenter.Panel.Children[0];
  87. var container = (ContentPresenter) child;
  88. container.UpdateChild();
  89. Assert.IsType<TextBlock>(container.Child);
  90. }
  91. [Fact]
  92. public void Should_Resolve_And_Embedd_Appropriate_View_Model()
  93. {
  94. var view = new ExampleView();
  95. view.ViewModel.Items.Add(new NestedViewModel());
  96. var child = view.List.Presenter.Panel.Children[0];
  97. var container = (ContentPresenter) child;
  98. container.UpdateChild();
  99. var host = (ViewModelViewHost) container.Child;
  100. Assert.IsType<NestedViewModel>(host.ViewModel);
  101. Assert.IsType<NestedViewModel>(host.DataContext);
  102. host.DataContext = "changed context";
  103. Assert.IsType<string>(host.ViewModel);
  104. Assert.IsType<string>(host.DataContext);
  105. }
  106. private static FuncDataTemplate GetItemTemplate()
  107. {
  108. return new FuncDataTemplate<TextBlock>((parent, scope) => new TextBlock());
  109. }
  110. private static FuncControlTemplate GetTemplate()
  111. {
  112. return new FuncControlTemplate<ItemsControl>((parent, scope) => new Border
  113. {
  114. Background = new Media.SolidColorBrush(0xffffffff),
  115. Child = new ItemsPresenter
  116. {
  117. Name = "PART_ItemsPresenter",
  118. [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
  119. }.RegisterInNameScope(scope)
  120. });
  121. }
  122. }
  123. }