BasicTests.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  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.Collections;
  4. using Avalonia.Controls;
  5. using Avalonia.Controls.Presenters;
  6. using Avalonia.Markup.Xaml.Data;
  7. using Avalonia.Markup.Xaml.Styling;
  8. using Avalonia.Markup.Xaml.Templates;
  9. using Avalonia.Media;
  10. using Avalonia.Styling;
  11. using Avalonia.UnitTests;
  12. using System.Collections;
  13. using System.ComponentModel;
  14. using System.Linq;
  15. using Xunit;
  16. namespace Avalonia.Markup.Xaml.UnitTests.Xaml
  17. {
  18. public class BasicTests
  19. {
  20. [Fact]
  21. public void Simple_Property_Is_Set()
  22. {
  23. var xaml = @"<ContentControl xmlns='https://github.com/avaloniaui' Content='Foo'/>";
  24. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  25. Assert.NotNull(target);
  26. Assert.Equal("Foo", target.Content);
  27. }
  28. [Fact]
  29. public void Default_Content_Property_Is_Set()
  30. {
  31. var xaml = @"<ContentControl xmlns='https://github.com/avaloniaui'>Foo</ContentControl>";
  32. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  33. Assert.NotNull(target);
  34. Assert.Equal("Foo", target.Content);
  35. }
  36. [Fact]
  37. public void AvaloniaProperty_Without_Getter_And_Setter_Is_Set()
  38. {
  39. var xaml =
  40. @"<local:NonControl xmlns='https://github.com/avaloniaui'
  41. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
  42. Foo='55' />";
  43. var target = AvaloniaXamlLoader.Parse<NonControl>(xaml);
  44. Assert.Equal(55, target.GetValue(NonControl.FooProperty));
  45. }
  46. [Fact]
  47. public void AvaloniaProperty_With_Getter_And_No_Setter_Is_Set()
  48. {
  49. var xaml =
  50. @"<local:NonControl xmlns='https://github.com/avaloniaui'
  51. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
  52. Bar='bar' />";
  53. var target = AvaloniaXamlLoader.Parse<NonControl>(xaml);
  54. Assert.Equal("bar", target.Bar);
  55. }
  56. [Fact]
  57. public void Attached_Property_Is_Set()
  58. {
  59. var xaml =
  60. @"<ContentControl xmlns='https://github.com/avaloniaui' TextBlock.FontSize='21'/>";
  61. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  62. Assert.NotNull(target);
  63. Assert.Equal(21.0, TextBlock.GetFontSize(target));
  64. }
  65. [Fact]
  66. public void Attached_Property_With_Namespace_Is_Set()
  67. {
  68. var xaml =
  69. @"<ContentControl xmlns='https://github.com/avaloniaui'
  70. xmlns:test='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'
  71. test:BasicTestsAttachedPropertyHolder.Foo='Bar'/>";
  72. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  73. Assert.NotNull(target);
  74. Assert.Equal("Bar", BasicTestsAttachedPropertyHolder.GetFoo(target));
  75. }
  76. [Fact]
  77. public void Attached_Property_Supports_Binding()
  78. {
  79. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  80. {
  81. var xaml =
  82. @"<Window xmlns='https://github.com/avaloniaui' TextBlock.FontSize='{Binding}'/>";
  83. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  84. target.DataContext = 21.0;
  85. Assert.Equal(21.0, TextBlock.GetFontSize(target));
  86. }
  87. }
  88. [Fact]
  89. public void Attached_Property_In_Panel_Is_Set()
  90. {
  91. var xaml = @"
  92. <Panel xmlns='https://github.com/avaloniaui'>
  93. <ToolTip.Tip>Foo</ToolTip.Tip>
  94. </Panel>";
  95. var target = AvaloniaXamlLoader.Parse<Panel>(xaml);
  96. Assert.Empty(target.Children);
  97. Assert.Equal("Foo", ToolTip.GetTip(target));
  98. }
  99. [Fact]
  100. public void ContentControl_ContentTemplate_Is_Functional()
  101. {
  102. var xaml =
  103. @"<ContentControl xmlns='https://github.com/avaloniaui'>
  104. <ContentControl.ContentTemplate>
  105. <DataTemplate>
  106. <TextBlock Text='Foo' />
  107. </DataTemplate>
  108. </ContentControl.ContentTemplate>
  109. </ContentControl>";
  110. var contentControl = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  111. var target = contentControl.ContentTemplate;
  112. Assert.NotNull(target);
  113. var txt = (TextBlock)target.Build(null);
  114. Assert.Equal("Foo", txt.Text);
  115. }
  116. [Fact]
  117. public void Named_Control_Is_Added_To_NameScope_Simple()
  118. {
  119. var xaml = @"
  120. <UserControl xmlns='https://github.com/avaloniaui'>
  121. <Button Name='button'>Foo</Button>
  122. </UserControl>";
  123. var control = AvaloniaXamlLoader.Parse<UserControl>(xaml);
  124. var button = control.FindControl<Button>("button");
  125. Assert.Equal("Foo", button.Content);
  126. }
  127. [Fact]
  128. public void Direct_Content_In_ItemsControl_Is_Operational()
  129. {
  130. using (UnitTestApplication.Start(TestServices.StyledWindow))
  131. {
  132. var xaml = @"
  133. <Window xmlns='https://github.com/avaloniaui'>
  134. <ItemsControl Name='items'>
  135. <ContentControl>Foo</ContentControl>
  136. <ContentControl>Bar</ContentControl>
  137. </ItemsControl>
  138. </Window>";
  139. var control = AvaloniaXamlLoader.Parse<Window>(xaml);
  140. var itemsControl = control.FindControl<ItemsControl>("items");
  141. Assert.NotNull(itemsControl);
  142. var items = itemsControl.Items.Cast<ContentControl>().ToArray();
  143. Assert.Equal("Foo", items[0].Content);
  144. Assert.Equal("Bar", items[1].Content);
  145. }
  146. }
  147. [Fact]
  148. public void Panel_Children_Are_Added()
  149. {
  150. var xaml = @"
  151. <UserControl xmlns='https://github.com/avaloniaui'>
  152. <Panel Name='panel'>
  153. <ContentControl Name='Foo' />
  154. <ContentControl Name='Bar' />
  155. </Panel>
  156. </UserControl>";
  157. var control = AvaloniaXamlLoader.Parse<UserControl>(xaml);
  158. var panel = control.FindControl<Panel>("panel");
  159. Assert.Equal(2, panel.Children.Count);
  160. var foo = control.FindControl<ContentControl>("Foo");
  161. var bar = control.FindControl<ContentControl>("Bar");
  162. Assert.Contains(foo, panel.Children);
  163. Assert.Contains(bar, panel.Children);
  164. }
  165. [Fact]
  166. public void Grid_Row_Col_Definitions_Are_Built()
  167. {
  168. var xaml = @"
  169. <Grid xmlns='https://github.com/avaloniaui'>
  170. <Grid.ColumnDefinitions>
  171. <ColumnDefinition Width='100' />
  172. <ColumnDefinition Width='Auto' />
  173. <ColumnDefinition Width='*' />
  174. <ColumnDefinition Width='100*' />
  175. </Grid.ColumnDefinitions>
  176. <Grid.RowDefinitions>
  177. <RowDefinition Height='100' />
  178. <RowDefinition Height='Auto' />
  179. <RowDefinition Height='*' />
  180. <RowDefinition Height='100*' />
  181. </Grid.RowDefinitions>
  182. </Grid>";
  183. var grid = AvaloniaXamlLoader.Parse<Grid>(xaml);
  184. Assert.Equal(4, grid.ColumnDefinitions.Count);
  185. Assert.Equal(4, grid.RowDefinitions.Count);
  186. var expected1 = new GridLength(100);
  187. var expected2 = GridLength.Auto;
  188. var expected3 = new GridLength(1, GridUnitType.Star);
  189. var expected4 = new GridLength(100, GridUnitType.Star);
  190. Assert.Equal(expected1, grid.ColumnDefinitions[0].Width);
  191. Assert.Equal(expected2, grid.ColumnDefinitions[1].Width);
  192. Assert.Equal(expected3, grid.ColumnDefinitions[2].Width);
  193. Assert.Equal(expected4, grid.ColumnDefinitions[3].Width);
  194. Assert.Equal(expected1, grid.RowDefinitions[0].Height);
  195. Assert.Equal(expected2, grid.RowDefinitions[1].Height);
  196. Assert.Equal(expected3, grid.RowDefinitions[2].Height);
  197. Assert.Equal(expected4, grid.RowDefinitions[3].Height);
  198. }
  199. [Fact]
  200. public void Grid_Row_Col_Definitions_Are_Parsed()
  201. {
  202. var xaml = @"
  203. <Grid xmlns='https://github.com/avaloniaui'
  204. ColumnDefinitions='100,Auto,*,100*'
  205. RowDefinitions='100,Auto,*,100*'>
  206. </Grid>";
  207. var grid = AvaloniaXamlLoader.Parse<Grid>(xaml);
  208. Assert.Equal(4, grid.ColumnDefinitions.Count);
  209. Assert.Equal(4, grid.RowDefinitions.Count);
  210. var expected1 = new GridLength(100);
  211. var expected2 = GridLength.Auto;
  212. var expected3 = new GridLength(1, GridUnitType.Star);
  213. var expected4 = new GridLength(100, GridUnitType.Star);
  214. Assert.Equal(expected1, grid.ColumnDefinitions[0].Width);
  215. Assert.Equal(expected2, grid.ColumnDefinitions[1].Width);
  216. Assert.Equal(expected3, grid.ColumnDefinitions[2].Width);
  217. Assert.Equal(expected4, grid.ColumnDefinitions[3].Width);
  218. Assert.Equal(expected1, grid.RowDefinitions[0].Height);
  219. Assert.Equal(expected2, grid.RowDefinitions[1].Height);
  220. Assert.Equal(expected3, grid.RowDefinitions[2].Height);
  221. Assert.Equal(expected4, grid.RowDefinitions[3].Height);
  222. }
  223. [Fact]
  224. public void ControlTemplate_With_Nested_Child_Is_Operational()
  225. {
  226. var xaml = @"
  227. <ControlTemplate xmlns='https://github.com/avaloniaui'>
  228. <ContentControl Name='parent'>
  229. <ContentControl Name='child' />
  230. </ContentControl>
  231. </ControlTemplate>
  232. ";
  233. var template = AvaloniaXamlLoader.Parse<ControlTemplate>(xaml);
  234. var parent = (ContentControl)template.Build(new ContentControl());
  235. Assert.Equal("parent", parent.Name);
  236. var child = parent.Content as ContentControl;
  237. Assert.NotNull(child);
  238. Assert.Equal("child", child.Name);
  239. }
  240. [Fact]
  241. public void ControlTemplate_With_Panel_Children_Are_Added()
  242. {
  243. var xaml = @"
  244. <ControlTemplate xmlns='https://github.com/avaloniaui'>
  245. <Panel Name='panel'>
  246. <ContentControl Name='Foo' />
  247. <ContentControl Name='Bar' />
  248. </Panel>
  249. </ControlTemplate>
  250. ";
  251. var template = AvaloniaXamlLoader.Parse<ControlTemplate>(xaml);
  252. var panel = (Panel)template.Build(new ContentControl());
  253. Assert.Equal(2, panel.Children.Count);
  254. var foo = panel.Children[0];
  255. var bar = panel.Children[1];
  256. Assert.Equal("Foo", foo.Name);
  257. Assert.Equal("Bar", bar.Name);
  258. }
  259. [Fact]
  260. public void Named_x_Control_Is_Added_To_NameScope_Simple()
  261. {
  262. var xaml = @"
  263. <UserControl xmlns='https://github.com/avaloniaui'
  264. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  265. <Button x:Name='button'>Foo</Button>
  266. </UserControl>";
  267. var control = AvaloniaXamlLoader.Parse<UserControl>(xaml);
  268. var button = control.FindControl<Button>("button");
  269. Assert.Equal("Foo", button.Content);
  270. }
  271. [Fact]
  272. public void Standart_TypeConverter_Is_Used()
  273. {
  274. var xaml = @"<UserControl xmlns='https://github.com/avaloniaui' Width='200.5' />";
  275. var control = AvaloniaXamlLoader.Parse<UserControl>(xaml);
  276. Assert.Equal(200.5, control.Width);
  277. }
  278. [Fact]
  279. public void Avalonia_TypeConverter_Is_Used()
  280. {
  281. var xaml = @"<UserControl xmlns='https://github.com/avaloniaui' Background='White' />";
  282. var control = AvaloniaXamlLoader.Parse<UserControl>(xaml);
  283. var bk = control.Background;
  284. Assert.IsType<SolidColorBrush>(bk);
  285. Assert.Equal(Colors.White, (bk as SolidColorBrush).Color);
  286. }
  287. [Fact]
  288. public void Simple_Style_Is_Parsed()
  289. {
  290. var xaml = @"
  291. <Styles xmlns='https://github.com/avaloniaui'
  292. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  293. <Style Selector='TextBlock'>
  294. <Setter Property='Background' Value='White'/>
  295. <Setter Property='Width' Value='100'/>
  296. </Style>
  297. </Styles>";
  298. var styles = AvaloniaXamlLoader.Parse<Styles>(xaml);
  299. Assert.Single(styles);
  300. var style = (Style)styles[0];
  301. var setters = style.Setters.Cast<Setter>().ToArray();
  302. Assert.Equal(2, setters.Length);
  303. Assert.Equal(TextBlock.BackgroundProperty, setters[0].Property);
  304. Assert.Equal(Brushes.White.Color, ((ISolidColorBrush)setters[0].Value).Color);
  305. Assert.Equal(TextBlock.WidthProperty, setters[1].Property);
  306. Assert.Equal(100.0, setters[1].Value);
  307. }
  308. [Fact]
  309. public void Style_Setter_With_AttachedProperty_Is_Parsed()
  310. {
  311. var xaml = @"
  312. <Styles xmlns='https://github.com/avaloniaui'
  313. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  314. <Style Selector='ContentControl'>
  315. <Setter Property='TextBlock.FontSize' Value='21'/>
  316. </Style>
  317. </Styles>";
  318. var styles = AvaloniaXamlLoader.Parse<Styles>(xaml);
  319. Assert.Single(styles);
  320. var style = (Style)styles[0];
  321. var setters = style.Setters.Cast<Setter>().ToArray();
  322. Assert.Single(setters);
  323. Assert.Equal(TextBlock.FontSizeProperty, setters[0].Property);
  324. Assert.Equal(21.0, setters[0].Value);
  325. }
  326. [Fact]
  327. public void Complex_Style_Is_Parsed()
  328. {
  329. using (UnitTestApplication.Start(TestServices.StyledWindow))
  330. {
  331. var xaml = @"
  332. <Styles xmlns='https://github.com/avaloniaui'>
  333. <Style Selector='CheckBox'>
  334. <Setter Property='BorderBrush' Value='{DynamicResource ThemeBorderMidBrush}'/>
  335. <Setter Property='BorderThickness' Value='{DynamicResource ThemeBorderThickness}'/>
  336. <Setter Property='Template'>
  337. <ControlTemplate>
  338. <Grid ColumnDefinitions='Auto,*'>
  339. <Border Name='border'
  340. BorderBrush='{TemplateBinding BorderBrush}'
  341. BorderThickness='{TemplateBinding BorderThickness}'
  342. Width='18'
  343. Height='18'
  344. VerticalAlignment='Center'>
  345. <Path Name='checkMark'
  346. Fill='{StaticResource HighlightBrush}'
  347. Width='11'
  348. Height='10'
  349. Stretch='Uniform'
  350. HorizontalAlignment='Center'
  351. VerticalAlignment='Center'
  352. Data='M 1145.607177734375,430 C1145.607177734375,430 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1141.449951171875,435.0772705078125 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1139.232177734375,433.0999755859375 1138,434.5538330078125 1138,434.5538330078125 1138,434.5538330078125 1141.482177734375,438 1141.482177734375,438 1141.482177734375,438 1141.96875,437.9375 1141.96875,437.9375 1141.96875,437.9375 1147,431.34619140625 1147,431.34619140625 1147,431.34619140625 1145.607177734375,430 1145.607177734375,430 z'/>
  353. </Border>
  354. <ContentPresenter Name='PART_ContentPresenter'
  355. Content='{TemplateBinding Content}'
  356. ContentTemplate='{TemplateBinding ContentTemplate}'
  357. Margin='4,0,0,0'
  358. VerticalAlignment='Center'
  359. Grid.Column='1'/>
  360. </Grid>
  361. </ControlTemplate>
  362. </Setter>
  363. </Style>
  364. </Styles>
  365. ";
  366. var styles = AvaloniaXamlLoader.Parse<Styles>(xaml);
  367. Assert.Single(styles);
  368. var style = (Style)styles[0];
  369. var setters = style.Setters.Cast<Setter>().ToArray();
  370. Assert.Equal(3, setters.Length);
  371. Assert.Equal(CheckBox.BorderBrushProperty, setters[0].Property);
  372. Assert.Equal(CheckBox.BorderThicknessProperty, setters[1].Property);
  373. Assert.Equal(CheckBox.TemplateProperty, setters[2].Property);
  374. Assert.IsType<ControlTemplate>(setters[2].Value);
  375. }
  376. }
  377. [Fact]
  378. public void Style_Resources_Are_Built()
  379. {
  380. var xaml = @"
  381. <Style xmlns='https://github.com/avaloniaui'
  382. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  383. xmlns:sys='clr-namespace:System;assembly=mscorlib'>
  384. <Style.Resources>
  385. <SolidColorBrush x:Key='Brush'>White</SolidColorBrush>
  386. <sys:Double x:Key='Double'>10</sys:Double>
  387. </Style.Resources>
  388. </Style>";
  389. var style = AvaloniaXamlLoader.Parse<Style>(xaml);
  390. Assert.True(style.Resources.Count > 0);
  391. style.TryGetResource("Brush", out var brush);
  392. Assert.NotNull(brush);
  393. Assert.Equal(Colors.White, ((SolidColorBrush)brush).Color);
  394. style.TryGetResource("Double", out var d);
  395. Assert.Equal(10.0, d);
  396. }
  397. [Fact]
  398. public void StyleInclude_Is_Built()
  399. {
  400. using (UnitTestApplication.Start(TestServices.StyledWindow))
  401. {
  402. var xaml = @"
  403. <Styles xmlns='https://github.com/avaloniaui'
  404. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  405. <StyleInclude Source='resm:Avalonia.Themes.Default.ContextMenu.xaml?assembly=Avalonia.Themes.Default'/>
  406. </Styles>";
  407. var styles = AvaloniaXamlLoader.Parse<Styles>(xaml);
  408. Assert.True(styles.Count == 1);
  409. var styleInclude = styles.First() as StyleInclude;
  410. Assert.NotNull(styleInclude);
  411. var style = styleInclude.Loaded;
  412. Assert.NotNull(style);
  413. }
  414. }
  415. [Fact]
  416. public void Simple_Xaml_Binding_Is_Operational()
  417. {
  418. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  419. .With(windowingPlatform: new MockWindowingPlatform())))
  420. {
  421. var xaml =
  422. @"<Window xmlns='https://github.com/avaloniaui' Content='{Binding}'/>";
  423. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  424. Assert.Null(target.Content);
  425. target.DataContext = "Foo";
  426. Assert.Equal("Foo", target.Content);
  427. }
  428. }
  429. [Fact]
  430. public void Xaml_Binding_Is_Delayed()
  431. {
  432. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  433. {
  434. var xaml =
  435. @"<ContentControl xmlns='https://github.com/avaloniaui' Content='{Binding}'/>";
  436. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  437. Assert.Null(target.Content);
  438. target.DataContext = "Foo";
  439. Assert.Null(target.Content);
  440. DelayedBinding.ApplyBindings(target);
  441. Assert.Equal("Foo", target.Content);
  442. }
  443. }
  444. [Fact]
  445. public void Double_Xaml_Binding_Is_Operational()
  446. {
  447. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  448. .With(windowingPlatform: new MockWindowingPlatform())))
  449. {
  450. var xaml =
  451. @"<Window xmlns='https://github.com/avaloniaui' Width='{Binding}'/>";
  452. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  453. Assert.Null(target.Content);
  454. target.DataContext = 55.0;
  455. Assert.Equal(55.0, target.Width);
  456. }
  457. }
  458. [Fact]
  459. public void Collection_Xaml_Binding_Is_Operational()
  460. {
  461. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  462. .With(windowingPlatform: new MockWindowingPlatform())))
  463. {
  464. var xaml = @"
  465. <Window xmlns='https://github.com/avaloniaui'>
  466. <ItemsControl Name='itemsControl' Items='{Binding}'>
  467. </ItemsControl>
  468. </Window>
  469. ";
  470. var target = AvaloniaXamlLoader.Parse<Window>(xaml);
  471. Assert.NotNull(target.Content);
  472. var itemsControl = target.FindControl<ItemsControl>("itemsControl");
  473. var items = new string[] { "Foo", "Bar" };
  474. //DelayedBinding.ApplyBindings(itemsControl);
  475. target.DataContext = items;
  476. Assert.Equal(items, itemsControl.Items);
  477. }
  478. }
  479. [Fact]
  480. public void Multi_Xaml_Binding_Is_Parsed()
  481. {
  482. var xaml =
  483. @"<MultiBinding xmlns='https://github.com/avaloniaui' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  484. Converter ='{x:Static BoolConverters.And}'>
  485. <Binding Path='Foo' />
  486. <Binding Path='Bar' />
  487. </MultiBinding>";
  488. var target = AvaloniaXamlLoader.Parse<MultiBinding>(xaml);
  489. Assert.Equal(2, target.Bindings.Count);
  490. Assert.Equal(BoolConverters.And, target.Converter);
  491. var bindings = target.Bindings.Cast<Binding>().ToArray();
  492. Assert.Equal("Foo", bindings[0].Path);
  493. Assert.Equal("Bar", bindings[1].Path);
  494. }
  495. [Fact]
  496. public void Control_Template_Is_Operational()
  497. {
  498. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  499. .With(windowingPlatform: new MockWindowingPlatform())))
  500. {
  501. var xaml = @"
  502. <Window xmlns='https://github.com/avaloniaui'
  503. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  504. <Window.Template>
  505. <ControlTemplate>
  506. <ContentPresenter Name='PART_ContentPresenter'
  507. Content='{TemplateBinding Content}'/>
  508. </ControlTemplate>
  509. </Window.Template>
  510. </Window>";
  511. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  512. Assert.NotNull(target.Template);
  513. Assert.Null(target.Presenter);
  514. target.ApplyTemplate();
  515. Assert.NotNull(target.Presenter);
  516. target.Content = "Foo";
  517. Assert.Equal("Foo", target.Presenter.Content);
  518. }
  519. }
  520. [Fact]
  521. public void Style_ControlTemplate_Is_Built()
  522. {
  523. var xaml = @"
  524. <Style xmlns='https://github.com/avaloniaui' Selector='ContentControl'>
  525. <Setter Property='Template'>
  526. <ControlTemplate>
  527. <ContentPresenter Name='PART_ContentPresenter'
  528. Content='{TemplateBinding Content}'
  529. ContentTemplate='{TemplateBinding ContentTemplate}' />
  530. </ControlTemplate>
  531. </Setter>
  532. </Style> ";
  533. var style = AvaloniaXamlLoader.Parse<Style>(xaml);
  534. Assert.Single(style.Setters);
  535. var setter = (Setter)style.Setters.First();
  536. Assert.Equal(ContentControl.TemplateProperty, setter.Property);
  537. Assert.IsType<ControlTemplate>(setter.Value);
  538. var template = (ControlTemplate)setter.Value;
  539. var control = new ContentControl();
  540. var result = (ContentPresenter)template.Build(control);
  541. Assert.NotNull(result);
  542. }
  543. [Fact]
  544. public void Named_Control_Is_Added_To_NameScope()
  545. {
  546. using (UnitTestApplication.Start(TestServices.StyledWindow))
  547. {
  548. var xaml = @"
  549. <Window xmlns='https://github.com/avaloniaui'
  550. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  551. <Button Name='button'>Foo</Button>
  552. </Window>";
  553. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  554. var button = window.FindControl<Button>("button");
  555. Assert.Equal("Foo", button.Content);
  556. }
  557. }
  558. [Fact(Skip =
  559. @"Doesn't work with Portable.xaml, it's working in different creation order -
  560. Handled in test 'Control_Is_Added_To_Parent_Before_Final_EndInit'
  561. do we need it?")]
  562. public void Control_Is_Added_To_Parent_Before_Properties_Are_Set()
  563. {
  564. using (UnitTestApplication.Start(TestServices.StyledWindow))
  565. {
  566. var xaml = @"
  567. <Window xmlns='https://github.com/avaloniaui'
  568. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  569. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  570. <local:InitializationOrderTracker Width='100'/>
  571. </Window>";
  572. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  573. var tracker = (InitializationOrderTracker)window.Content;
  574. var attached = tracker.Order.IndexOf("AttachedToLogicalTree");
  575. var widthChanged = tracker.Order.IndexOf("Property Width Changed");
  576. Assert.NotEqual(-1, attached);
  577. Assert.NotEqual(-1, widthChanged);
  578. Assert.True(attached < widthChanged);
  579. }
  580. }
  581. [Fact]
  582. public void Control_Is_Added_To_Parent_Before_Final_EndInit()
  583. {
  584. using (UnitTestApplication.Start(TestServices.StyledWindow))
  585. {
  586. var xaml = @"
  587. <Window xmlns='https://github.com/avaloniaui'
  588. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  589. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  590. <local:InitializationOrderTracker Width='100'/>
  591. </Window>";
  592. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  593. var tracker = (InitializationOrderTracker)window.Content;
  594. var attached = tracker.Order.IndexOf("AttachedToLogicalTree");
  595. var endInit = tracker.Order.IndexOf("EndInit 0");
  596. Assert.NotEqual(-1, attached);
  597. Assert.NotEqual(-1, endInit);
  598. Assert.True(attached < endInit);
  599. }
  600. }
  601. [Fact]
  602. public void All_Properties_Are_Set_Before_Final_EndInit()
  603. {
  604. using (UnitTestApplication.Start(TestServices.StyledWindow))
  605. {
  606. var xaml = @"
  607. <Window xmlns='https://github.com/avaloniaui'
  608. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  609. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  610. <local:InitializationOrderTracker Width='100' Height='100'
  611. Tag='{Binding Height, RelativeSource={RelativeSource Self}}' />
  612. </Window>";
  613. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  614. var tracker = (InitializationOrderTracker)window.Content;
  615. //ensure binding is set and operational first
  616. Assert.Equal(100.0, tracker.Tag);
  617. Assert.Equal("EndInit 0", tracker.Order.Last());
  618. }
  619. }
  620. [Fact]
  621. public void BeginInit_Matches_EndInit()
  622. {
  623. using (UnitTestApplication.Start(TestServices.StyledWindow))
  624. {
  625. var xaml = @"
  626. <Window xmlns='https://github.com/avaloniaui'
  627. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  628. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  629. <local:InitializationOrderTracker />
  630. </Window>";
  631. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  632. var tracker = (InitializationOrderTracker)window.Content;
  633. Assert.Equal(0, tracker.InitState);
  634. }
  635. }
  636. [Fact]
  637. public void DeferedXamlLoader_Should_Preserve_NamespacesContext()
  638. {
  639. var xaml =
  640. @"<ContentControl xmlns='https://github.com/avaloniaui'
  641. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  642. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  643. <ContentControl.ContentTemplate>
  644. <DataTemplate>
  645. <TextBlock Tag='{x:Static local:NonControl.StringProperty}'/>
  646. </DataTemplate>
  647. </ContentControl.ContentTemplate>
  648. </ContentControl>";
  649. var contentControl = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  650. var template = contentControl.ContentTemplate;
  651. Assert.NotNull(template);
  652. var txt = (TextBlock)template.Build(null);
  653. Assert.Equal((object)NonControl.StringProperty, txt.Tag);
  654. }
  655. [Fact]
  656. public void Binding_To_List_AvaloniaProperty_Is_Operational()
  657. {
  658. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  659. {
  660. var xaml = @"
  661. <Window xmlns='https://github.com/avaloniaui'>
  662. <ListBox Items='{Binding Items}' SelectedItems='{Binding SelectedItems}'/>
  663. </Window>";
  664. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  665. var listBox = (ListBox)window.Content;
  666. var vm = new SelectedItemsViewModel()
  667. {
  668. Items = new string[] { "foo", "bar", "baz" }
  669. };
  670. window.DataContext = vm;
  671. Assert.Equal(vm.Items, listBox.Items);
  672. Assert.Equal(vm.SelectedItems, listBox.SelectedItems);
  673. }
  674. }
  675. private class SelectedItemsViewModel : INotifyPropertyChanged
  676. {
  677. public string[] Items { get; set; }
  678. public event PropertyChangedEventHandler PropertyChanged;
  679. private IList _selectedItems = new AvaloniaList<string>();
  680. public IList SelectedItems
  681. {
  682. get { return _selectedItems; }
  683. set
  684. {
  685. _selectedItems = value;
  686. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItems)));
  687. }
  688. }
  689. }
  690. }
  691. public class BasicTestsAttachedPropertyHolder
  692. {
  693. public static AvaloniaProperty<string> FooProperty =
  694. AvaloniaProperty.RegisterAttached<BasicTestsAttachedPropertyHolder, AvaloniaObject, string>("Foo");
  695. public static void SetFoo(AvaloniaObject target, string value) => target.SetValue(FooProperty, value);
  696. public static string GetFoo(AvaloniaObject target) => (string)target.GetValue(FooProperty);
  697. }
  698. }