BasicTests.cs 29 KB

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