BindingTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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 System.Reactive.Subjects;
  4. using Avalonia.Controls;
  5. using Avalonia.UnitTests;
  6. using Xunit;
  7. namespace Avalonia.Markup.Xaml.UnitTests.Xaml
  8. {
  9. public class BindingTests
  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}'/>
  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 Longhand_Binding_To_DataContext_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'>
  40. <Button.Content>
  41. <Binding Path='Foo'/>
  42. </Button.Content>
  43. </Button>
  44. </Window>";
  45. var loader = new AvaloniaXamlLoader();
  46. var window = (Window)loader.Load(xaml);
  47. var button = window.FindControl<Button>("button");
  48. button.DataContext = new { Foo = "foo" };
  49. window.ApplyTemplate();
  50. Assert.Equal("foo", button.Content);
  51. }
  52. }
  53. [Fact]
  54. public void Can_Bind_Control_To_Non_Control()
  55. {
  56. using (UnitTestApplication.Start(TestServices.StyledWindow))
  57. {
  58. var xaml = @"
  59. <Window xmlns='https://github.com/avaloniaui'
  60. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  61. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  62. <Button Name='button' Content='Foo'>
  63. <Button.Tag>
  64. <local:NonControl Control='{Binding #button}'/>
  65. </Button.Tag>
  66. </Button>
  67. </Window>";
  68. var loader = new AvaloniaXamlLoader();
  69. var window = (Window)loader.Load(xaml);
  70. var button = window.FindControl<Button>("button");
  71. Assert.Same(button, ((NonControl)button.Tag).Control);
  72. }
  73. }
  74. [Fact]
  75. public void Can_Bind_To_DataContext_Of_Anchor_On_Non_Control()
  76. {
  77. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  78. {
  79. var xaml = @"
  80. <Window xmlns='https://github.com/avaloniaui'
  81. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  82. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  83. <Button Name='button'>
  84. <Button.Tag>
  85. <local:NonControl String='{Binding Foo}'/>
  86. </Button.Tag>
  87. </Button>
  88. </Window>";
  89. var loader = new AvaloniaXamlLoader();
  90. var window = (Window)loader.Load(xaml);
  91. var button = window.FindControl<Button>("button");
  92. button.DataContext = new { Foo = "foo" };
  93. Assert.Equal("foo", ((NonControl)button.Tag).String);
  94. }
  95. }
  96. [Fact]
  97. public void Binding_To_Window_Works()
  98. {
  99. using (UnitTestApplication.Start(TestServices.StyledWindow))
  100. {
  101. var xaml = @"
  102. <Window xmlns='https://github.com/avaloniaui'
  103. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  104. Title='{Binding Foo}'>
  105. </Window>";
  106. var loader = new AvaloniaXamlLoader();
  107. var window = (Window)loader.Load(xaml);
  108. window.DataContext = new { Foo = "foo" };
  109. window.ApplyTemplate();
  110. Assert.Equal("foo", window.Title);
  111. }
  112. }
  113. [Fact]
  114. public void Binding_DataContext_To_Inherited_DataContext_Works()
  115. {
  116. using (UnitTestApplication.Start(TestServices.StyledWindow))
  117. {
  118. var xaml = @"
  119. <Window xmlns='https://github.com/avaloniaui'
  120. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  121. <Border DataContext='{Binding Foo}'/>
  122. </Window>";
  123. var loader = new AvaloniaXamlLoader();
  124. var window = (Window)loader.Load(xaml);
  125. var border = (Border)window.Content;
  126. window.DataContext = new { Foo = "foo" };
  127. window.ApplyTemplate();
  128. Assert.Equal("foo", border.DataContext);
  129. }
  130. }
  131. [Fact]
  132. public void Binding_To_Self_Works()
  133. {
  134. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  135. {
  136. var xaml = @"
  137. <Window xmlns='https://github.com/avaloniaui'
  138. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  139. <TextBlock Name='textblock' Text='{Binding Tag, RelativeSource={RelativeSource Self}}'/>
  140. </Window>";
  141. var window = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  142. var textBlock = (TextBlock)window.Content;
  143. textBlock.Tag = "foo";
  144. Assert.Equal("foo", textBlock.Text);
  145. }
  146. }
  147. [Fact]
  148. public void Longform_Binding_To_Self_Works()
  149. {
  150. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  151. {
  152. var xaml = @"
  153. <Window xmlns='https://github.com/avaloniaui'
  154. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  155. <TextBlock Name='textblock' Tag='foo'>
  156. <TextBlock.Text>
  157. <Binding RelativeSource='{RelativeSource Self}' Path='Tag'/>
  158. </TextBlock.Text>
  159. </TextBlock>
  160. </Window>";
  161. var loader = new AvaloniaXamlLoader();
  162. var window = (Window)loader.Load(xaml);
  163. var textBlock = (TextBlock)window.Content;
  164. window.ApplyTemplate();
  165. Assert.Equal("foo", textBlock.Text);
  166. }
  167. }
  168. [Fact]
  169. public void Stream_Binding_To_Observable_Works()
  170. {
  171. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  172. {
  173. var xaml = @"
  174. <Window xmlns='https://github.com/avaloniaui'
  175. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  176. <TextBlock Name='textblock' Text='{Binding Observable^}'/>
  177. </Window>";
  178. var loader = new AvaloniaXamlLoader();
  179. var window = (Window)loader.Load(xaml);
  180. var textBlock = (TextBlock)window.Content;
  181. var observable = new BehaviorSubject<string>("foo");
  182. window.DataContext = new { Observable = observable };
  183. window.ApplyTemplate();
  184. Assert.Equal("foo", textBlock.Text);
  185. observable.OnNext("bar");
  186. Assert.Equal("bar", textBlock.Text);
  187. }
  188. }
  189. [Fact]
  190. public void Binding_To_Namespaced_Attached_Property_Works()
  191. {
  192. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  193. {
  194. var xaml = @"
  195. <Window xmlns='https://github.com/avaloniaui'
  196. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  197. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  198. <TextBlock local:AttachedPropertyOwner.Double='{Binding}'/>
  199. </Window>";
  200. var loader = new AvaloniaXamlLoader();
  201. var window = (Window)loader.Load(xaml);
  202. var textBlock = (TextBlock)window.Content;
  203. window.DataContext = 5.6;
  204. window.ApplyTemplate();
  205. Assert.Equal(5.6, AttachedPropertyOwner.GetDouble(textBlock));
  206. }
  207. }
  208. [Fact]
  209. public void Binding_To_AddOwnered_Attached_Property_Works()
  210. {
  211. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  212. {
  213. var xaml = @"
  214. <Window xmlns='https://github.com/avaloniaui'
  215. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  216. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  217. <local:TestControl Double='{Binding}'/>
  218. </Window>";
  219. var loader = new AvaloniaXamlLoader();
  220. var window = (Window)loader.Load(xaml);
  221. var testControl = (TestControl)window.Content;
  222. window.DataContext = 5.6;
  223. window.ApplyTemplate();
  224. Assert.Equal(5.6, testControl.Double);
  225. }
  226. }
  227. [Fact]
  228. public void Binding_To_Attached_Property_Using_AddOwnered_Type_Works()
  229. {
  230. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  231. {
  232. var xaml = @"
  233. <Window xmlns='https://github.com/avaloniaui'
  234. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  235. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  236. <TextBlock local:TestControl.Double='{Binding}'/>
  237. </Window>";
  238. var loader = new AvaloniaXamlLoader();
  239. var window = (Window)loader.Load(xaml);
  240. var textBlock = (TextBlock)window.Content;
  241. window.DataContext = 5.6;
  242. window.ApplyTemplate();
  243. Assert.Equal(5.6, AttachedPropertyOwner.GetDouble(textBlock));
  244. }
  245. }
  246. [Fact]
  247. public void Binding_To_Attached_Property_In_Style_Works()
  248. {
  249. using (UnitTestApplication.Start(TestServices.StyledWindow))
  250. {
  251. var xaml = @"
  252. <Window xmlns='https://github.com/avaloniaui'
  253. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  254. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  255. <Window.Styles>
  256. <Style Selector='TextBlock'>
  257. <Setter Property='local:TestControl.Double' Value='{Binding}'/>
  258. </Style>
  259. </Window.Styles>
  260. <TextBlock/>
  261. </Window>";
  262. var loader = new AvaloniaXamlLoader();
  263. var window = (Window)loader.Load(xaml);
  264. var textBlock = (TextBlock)window.Content;
  265. window.DataContext = 5.6;
  266. window.ApplyTemplate();
  267. Assert.Equal(5.6, AttachedPropertyOwner.GetDouble(textBlock));
  268. }
  269. }
  270. [Fact]
  271. public void Binding_To_TextBlock_Text_With_StringConverter_Works()
  272. {
  273. using (UnitTestApplication.Start(TestServices.StyledWindow))
  274. {
  275. var xaml = @"
  276. <Window xmlns='https://github.com/avaloniaui'
  277. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  278. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  279. <TextBlock Name='textBlock' Text='{Binding Foo, StringFormat=Hello \{0\}}'/>
  280. </Window>";
  281. var loader = new AvaloniaXamlLoader();
  282. var window = (Window)loader.Load(xaml);
  283. var textBlock = window.FindControl<TextBlock>("textBlock");
  284. textBlock.DataContext = new { Foo = "world" };
  285. window.ApplyTemplate();
  286. Assert.Equal("Hello world", textBlock.Text);
  287. }
  288. }
  289. }
  290. }