BasicTests.cs 31 KB

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