BindingTests_RelativeSource.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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 Avalonia.Controls;
  4. using Avalonia.UnitTests;
  5. using System;
  6. using Xunit;
  7. namespace Avalonia.Markup.Xaml.UnitTests.Xaml
  8. {
  9. public class BindingTests_RelativeSource : XamlTestBase
  10. {
  11. [Fact]
  12. public void Binding_To_DataContext_Works()
  13. {
  14. using (UnitTestApplication.Start(TestServices.StyledWindow))
  15. {
  16. var xaml = @"
  17. <Window xmlns='https://github.com/avaloniaui'
  18. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  19. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  20. <Button Name='button' Content='{Binding Foo, RelativeSource={RelativeSource DataContext}}'/>
  21. </Window>";
  22. var loader = new AvaloniaXamlLoader();
  23. var window = (Window)loader.Load(xaml);
  24. var button = window.FindControl<Button>("button");
  25. button.DataContext = new { Foo = "foo" };
  26. window.ApplyTemplate();
  27. Assert.Equal("foo", button.Content);
  28. }
  29. }
  30. [Fact]
  31. public void Binding_To_Self_Works()
  32. {
  33. using (UnitTestApplication.Start(TestServices.StyledWindow))
  34. {
  35. var xaml = @"
  36. <Window xmlns='https://github.com/avaloniaui'
  37. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  38. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  39. <Button Name='button' Content='{Binding Name, RelativeSource={RelativeSource Self}}'/>
  40. </Window>";
  41. var loader = new AvaloniaXamlLoader();
  42. var window = (Window)loader.Load(xaml);
  43. var button = window.FindControl<Button>("button");
  44. window.ApplyTemplate();
  45. Assert.Equal("button", button.Content);
  46. }
  47. }
  48. [Fact]
  49. public void Binding_To_First_Ancestor_Works()
  50. {
  51. using (UnitTestApplication.Start(TestServices.StyledWindow))
  52. {
  53. var xaml = @"
  54. <Window xmlns='https://github.com/avaloniaui'
  55. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  56. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  57. <Border Name='border1'>
  58. <Border Name='border2'>
  59. <Button Name='button' Content='{Binding Name, RelativeSource={RelativeSource AncestorType=Border}}'/>
  60. </Border>
  61. </Border>
  62. </Window>";
  63. var loader = new AvaloniaXamlLoader();
  64. var window = (Window)loader.Load(xaml);
  65. var button = window.FindControl<Button>("button");
  66. window.ApplyTemplate();
  67. window.Presenter.ApplyTemplate();
  68. Assert.Equal("border2", button.Content);
  69. }
  70. }
  71. [Fact]
  72. public void Binding_To_First_Ancestor_Without_AncestorType_Throws_Exception()
  73. {
  74. using (UnitTestApplication.Start(TestServices.StyledWindow))
  75. {
  76. var xaml = @"
  77. <Window xmlns='https://github.com/avaloniaui'
  78. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  79. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  80. <Border Name='border1'>
  81. <ContentControl Name='contentControl'>
  82. <Button Name='button' Content='{Binding Name, RelativeSource={RelativeSource AncestorLevel=1}}'/>
  83. </ContentControl>
  84. </Border>
  85. </Window>";
  86. var loader = new AvaloniaXamlLoader();
  87. Assert.Throws<InvalidOperationException>( () => loader.Load(xaml));
  88. }
  89. }
  90. [Fact]
  91. public void Binding_To_First_Ancestor_With_Shorthand_Works()
  92. {
  93. using (UnitTestApplication.Start(TestServices.StyledWindow))
  94. {
  95. var xaml = @"
  96. <Window xmlns='https://github.com/avaloniaui'
  97. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  98. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  99. <Border Name='border1'>
  100. <Border Name='border2'>
  101. <Button Name='button' Content='{Binding $parent.Name}'/>
  102. </Border>
  103. </Border>
  104. </Window>";
  105. var loader = new AvaloniaXamlLoader();
  106. var window = (Window)loader.Load(xaml);
  107. var button = window.FindControl<Button>("button");
  108. window.ApplyTemplate();
  109. Assert.Equal("border2", button.Content);
  110. }
  111. }
  112. [Fact]
  113. public void Binding_To_First_Ancestor_With_Shorthand_Uses_LogicalTree()
  114. {
  115. using (UnitTestApplication.Start(TestServices.StyledWindow))
  116. {
  117. var xaml = @"
  118. <Window xmlns='https://github.com/avaloniaui'
  119. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  120. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  121. <Border Name='border'>
  122. <ContentControl Name='contentControl'>
  123. <Button Name='button' Content='{Binding $parent.Name}'/>
  124. </ContentControl>
  125. </Border>
  126. </Window>";
  127. var loader = new AvaloniaXamlLoader();
  128. var window = (Window)loader.Load(xaml);
  129. var contentControl = window.FindControl<ContentControl>("contentControl");
  130. var button = window.FindControl<Button>("button");
  131. window.ApplyTemplate();
  132. Assert.Equal("contentControl", button.Content);
  133. }
  134. }
  135. [Fact]
  136. public void Binding_To_Second_Ancestor_Works()
  137. {
  138. using (UnitTestApplication.Start(TestServices.StyledWindow))
  139. {
  140. var xaml = @"
  141. <Window xmlns='https://github.com/avaloniaui'
  142. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  143. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  144. <Border Name='border1'>
  145. <Border Name='border2'>
  146. <Button Name='button' Content='{Binding Name, RelativeSource={RelativeSource AncestorType=Border, AncestorLevel=2}}'/>
  147. </Border>
  148. </Border>
  149. </Window>";
  150. var loader = new AvaloniaXamlLoader();
  151. var window = (Window)loader.Load(xaml);
  152. var button = window.FindControl<Button>("button");
  153. window.ApplyTemplate();
  154. window.Presenter.ApplyTemplate();
  155. Assert.Equal("border1", button.Content);
  156. }
  157. }
  158. [Fact]
  159. public void Binding_To_Second_Ancestor_With_Shorthand_Uses_LogicalTree()
  160. {
  161. using (UnitTestApplication.Start(TestServices.StyledWindow))
  162. {
  163. var xaml = @"
  164. <Window xmlns='https://github.com/avaloniaui'
  165. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  166. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  167. <ContentControl Name='contentControl1'>
  168. <ContentControl Name='contentControl2'>
  169. <Button Name='button' Content='{Binding $parent[1].Name}'/>
  170. </ContentControl>
  171. </ContentControl>
  172. </Window>";
  173. var loader = new AvaloniaXamlLoader();
  174. var window = (Window)loader.Load(xaml);
  175. var contentControl1 = window.FindControl<ContentControl>("contentControl1");
  176. var contentControl2 = window.FindControl<ContentControl>("contentControl2");
  177. var button = window.FindControl<Button>("button");
  178. window.ApplyTemplate();
  179. Assert.Equal("contentControl1", button.Content);
  180. }
  181. }
  182. [Fact]
  183. public void Binding_To_Ancestor_Of_Type_With_Shorthand_Works()
  184. {
  185. using (UnitTestApplication.Start(TestServices.StyledWindow))
  186. {
  187. var xaml = @"
  188. <Window xmlns='https://github.com/avaloniaui'
  189. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  190. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  191. <Border Name='border1'>
  192. <Border Name='border2'>
  193. <Button Name='button' Content='{Binding $parent[Border].Name}'/>
  194. </Border>
  195. </Border>
  196. </Window>";
  197. var loader = new AvaloniaXamlLoader();
  198. var window = (Window)loader.Load(xaml);
  199. var button = window.FindControl<Button>("button");
  200. window.ApplyTemplate();
  201. Assert.Equal("border2", button.Content);
  202. }
  203. }
  204. [Fact]
  205. public void Binding_To_Second_Ancestor_With_Shorthand_And_Type_Works()
  206. {
  207. using (UnitTestApplication.Start(TestServices.StyledWindow))
  208. {
  209. var xaml = @"
  210. <Window xmlns='https://github.com/avaloniaui'
  211. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  212. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  213. <Border Name='border1'>
  214. <Border Name='border2'>
  215. <Button Name='button' Content='{Binding $parent[Border; 1].Name}'/>
  216. </Border>
  217. </Border>
  218. </Window>";
  219. var loader = new AvaloniaXamlLoader();
  220. var window = (Window)loader.Load(xaml);
  221. var button = window.FindControl<Button>("button");
  222. window.ApplyTemplate();
  223. Assert.Equal("border1", button.Content);
  224. }
  225. }
  226. [Fact]
  227. public void Binding_To_Second_Ancestor_With_Shorthand_Works()
  228. {
  229. using (UnitTestApplication.Start(TestServices.StyledWindow))
  230. {
  231. var xaml = @"
  232. <Window xmlns='https://github.com/avaloniaui'
  233. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  234. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  235. <Border Name='border1'>
  236. <Border Name='border2'>
  237. <Button Name='button' Content='{Binding $parent[1].Name}'/>
  238. </Border>
  239. </Border>
  240. </Window>";
  241. var loader = new AvaloniaXamlLoader();
  242. var window = (Window)loader.Load(xaml);
  243. var button = window.FindControl<Button>("button");
  244. window.ApplyTemplate();
  245. Assert.Equal("border1", button.Content);
  246. }
  247. }
  248. [Fact]
  249. public void Binding_To_Ancestor_With_Namespace_Works()
  250. {
  251. using (UnitTestApplication.Start(TestServices.StyledWindow))
  252. {
  253. var xaml = @"
  254. <local:TestWindow xmlns='https://github.com/avaloniaui'
  255. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  256. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
  257. Title='title'>
  258. <Button Name='button' Content='{Binding Title, RelativeSource={RelativeSource AncestorType=local:TestWindow}}'/>
  259. </local:TestWindow>";
  260. var loader = new AvaloniaXamlLoader();
  261. var window = (TestWindow)loader.Load(xaml);
  262. var button = window.FindControl<Button>("button");
  263. window.ApplyTemplate();
  264. window.Presenter.ApplyTemplate();
  265. Assert.Equal("title", button.Content);
  266. }
  267. }
  268. [Fact]
  269. public void Shorthand_Binding_With_Negation_Works()
  270. {
  271. using (UnitTestApplication.Start(TestServices.StyledWindow))
  272. {
  273. var xaml = @"
  274. <Window xmlns='https://github.com/avaloniaui'
  275. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  276. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  277. <Border Name='border1'>
  278. <Border Name='border2'>
  279. <Button Name='button' Content='{Binding !$self.IsDefault}'/>
  280. </Border>
  281. </Border>
  282. </Window>";
  283. var loader = new AvaloniaXamlLoader();
  284. var window = (Window)loader.Load(xaml);
  285. var button = window.FindControl<Button>("button");
  286. window.ApplyTemplate();
  287. #pragma warning disable xUnit2004 // Diagnostic mis-firing since button.Content isn't guaranteed to be a bool.
  288. Assert.Equal(true, button.Content);
  289. #pragma warning restore xUnit2004
  290. }
  291. }
  292. [Fact]
  293. public void Shorthand_Binding_With_Multiple_Negation_Works()
  294. {
  295. using (UnitTestApplication.Start(TestServices.StyledWindow))
  296. {
  297. var xaml = @"
  298. <Window xmlns='https://github.com/avaloniaui'
  299. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  300. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  301. <Border Name='border1'>
  302. <Border Name='border2'>
  303. <Button Name='button' Content='{Binding !!$self.IsDefault}'/>
  304. </Border>
  305. </Border>
  306. </Window>";
  307. var loader = new AvaloniaXamlLoader();
  308. var window = (Window)loader.Load(xaml);
  309. var button = window.FindControl<Button>("button");
  310. window.ApplyTemplate();
  311. #pragma warning disable xUnit2004 // Diagnostic mis-firing since button.Content isn't guaranteed to be a bool.
  312. Assert.Equal(false, button.Content);
  313. #pragma warning restore xUnit2004
  314. }
  315. }
  316. }
  317. public class TestWindow : Window { }
  318. }