BasicTests.cs 30 KB

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