BasicTests.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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='{DynamicResource ThemeBorderMidBrush}'/>
  324. <Setter Property='BorderThickness' Value='{DynamicResource 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='{StaticResource 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<ControlTemplate>(setters[2].Value);
  364. }
  365. }
  366. [Fact]
  367. public void Style_Resources_Are_Built()
  368. {
  369. var xaml = @"
  370. <Style xmlns='https://github.com/avaloniaui'
  371. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  372. xmlns:sys='clr-namespace:System;assembly=mscorlib'>
  373. <Style.Resources>
  374. <SolidColorBrush x:Key='Brush'>White</SolidColorBrush>
  375. <sys:Double x:Key='Double'>10</sys:Double>
  376. </Style.Resources>
  377. </Style>";
  378. var style = AvaloniaXamlLoader.Parse<Style>(xaml);
  379. Assert.True(style.Resources.Count > 0);
  380. style.TryGetResource("Brush", out var brush);
  381. Assert.NotNull(brush);
  382. Assert.Equal(Colors.White, ((SolidColorBrush)brush).Color);
  383. style.TryGetResource("Double", out var d);
  384. Assert.Equal(10.0, d);
  385. }
  386. [Fact]
  387. public void StyleInclude_Is_Built()
  388. {
  389. using (UnitTestApplication.Start(TestServices.StyledWindow))
  390. {
  391. var xaml = @"
  392. <Styles xmlns='https://github.com/avaloniaui'
  393. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  394. <StyleInclude Source='resm:Avalonia.Themes.Default.ContextMenu.xaml?assembly=Avalonia.Themes.Default'/>
  395. </Styles>";
  396. var styles = AvaloniaXamlLoader.Parse<Styles>(xaml);
  397. Assert.True(styles.Count == 1);
  398. var styleInclude = styles.First() as StyleInclude;
  399. Assert.NotNull(styleInclude);
  400. var style = styleInclude.Loaded;
  401. Assert.NotNull(style);
  402. }
  403. }
  404. [Fact]
  405. public void Simple_Xaml_Binding_Is_Operational()
  406. {
  407. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  408. .With(windowingPlatform: new MockWindowingPlatform())))
  409. {
  410. var xaml =
  411. @"<Window xmlns='https://github.com/avaloniaui' Content='{Binding}'/>";
  412. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  413. Assert.Null(target.Content);
  414. target.DataContext = "Foo";
  415. Assert.Equal("Foo", target.Content);
  416. }
  417. }
  418. [Fact]
  419. public void Xaml_Binding_Is_Delayed()
  420. {
  421. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  422. {
  423. var xaml =
  424. @"<ContentControl xmlns='https://github.com/avaloniaui' Content='{Binding}'/>";
  425. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  426. Assert.Null(target.Content);
  427. target.DataContext = "Foo";
  428. Assert.Null(target.Content);
  429. DelayedBinding.ApplyBindings(target);
  430. Assert.Equal("Foo", target.Content);
  431. }
  432. }
  433. [Fact]
  434. public void Double_Xaml_Binding_Is_Operational()
  435. {
  436. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  437. .With(windowingPlatform: new MockWindowingPlatform())))
  438. {
  439. var xaml =
  440. @"<Window xmlns='https://github.com/avaloniaui' Width='{Binding}'/>";
  441. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  442. Assert.Null(target.Content);
  443. target.DataContext = 55.0;
  444. Assert.Equal(55.0, target.Width);
  445. }
  446. }
  447. [Fact]
  448. public void Collection_Xaml_Binding_Is_Operational()
  449. {
  450. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  451. .With(windowingPlatform: new MockWindowingPlatform())))
  452. {
  453. var xaml = @"
  454. <Window xmlns='https://github.com/avaloniaui'>
  455. <ItemsControl Name='itemsControl' Items='{Binding}'>
  456. </ItemsControl>
  457. </Window>
  458. ";
  459. var target = AvaloniaXamlLoader.Parse<Window>(xaml);
  460. Assert.NotNull(target.Content);
  461. var itemsControl = target.FindControl<ItemsControl>("itemsControl");
  462. var items = new string[] { "Foo", "Bar" };
  463. //DelayedBinding.ApplyBindings(itemsControl);
  464. target.DataContext = items;
  465. Assert.Equal(items, itemsControl.Items);
  466. }
  467. }
  468. [Fact]
  469. public void Multi_Xaml_Binding_Is_Parsed()
  470. {
  471. var xaml =
  472. @"<MultiBinding xmlns='https://github.com/avaloniaui' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  473. Converter ='{x:Static BoolConverters.And}'>
  474. <Binding Path='Foo' />
  475. <Binding Path='Bar' />
  476. </MultiBinding>";
  477. var target = AvaloniaXamlLoader.Parse<MultiBinding>(xaml);
  478. Assert.Equal(2, target.Bindings.Count);
  479. Assert.Equal(BoolConverters.And, target.Converter);
  480. var bindings = target.Bindings.Cast<Binding>().ToArray();
  481. Assert.Equal("Foo", bindings[0].Path);
  482. Assert.Equal("Bar", bindings[1].Path);
  483. }
  484. [Fact]
  485. public void Control_Template_Is_Operational()
  486. {
  487. using (UnitTestApplication.Start(TestServices.MockPlatformWrapper
  488. .With(windowingPlatform: new MockWindowingPlatform())))
  489. {
  490. var xaml = @"
  491. <Window xmlns='https://github.com/avaloniaui'
  492. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  493. <Window.Template>
  494. <ControlTemplate>
  495. <ContentPresenter Name='PART_ContentPresenter'
  496. Content='{TemplateBinding Content}'/>
  497. </ControlTemplate>
  498. </Window.Template>
  499. </Window>";
  500. var target = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  501. Assert.NotNull(target.Template);
  502. Assert.Null(target.Presenter);
  503. target.ApplyTemplate();
  504. Assert.NotNull(target.Presenter);
  505. target.Content = "Foo";
  506. Assert.Equal("Foo", target.Presenter.Content);
  507. }
  508. }
  509. [Fact]
  510. public void Style_ControlTemplate_Is_Built()
  511. {
  512. var xaml = @"
  513. <Style xmlns='https://github.com/avaloniaui' Selector='ContentControl'>
  514. <Setter Property='Template'>
  515. <ControlTemplate>
  516. <ContentPresenter Name='PART_ContentPresenter'
  517. Content='{TemplateBinding Content}'
  518. ContentTemplate='{TemplateBinding ContentTemplate}' />
  519. </ControlTemplate>
  520. </Setter>
  521. </Style> ";
  522. var style = AvaloniaXamlLoader.Parse<Style>(xaml);
  523. Assert.Equal(1, style.Setters.Count());
  524. var setter = (Setter)style.Setters.First();
  525. Assert.Equal(ContentControl.TemplateProperty, setter.Property);
  526. Assert.IsType<ControlTemplate>(setter.Value);
  527. var template = (ControlTemplate)setter.Value;
  528. var control = new ContentControl();
  529. var result = (ContentPresenter)template.Build(control);
  530. Assert.NotNull(result);
  531. }
  532. [Fact]
  533. public void Named_Control_Is_Added_To_NameScope()
  534. {
  535. using (UnitTestApplication.Start(TestServices.StyledWindow))
  536. {
  537. var xaml = @"
  538. <Window xmlns='https://github.com/avaloniaui'
  539. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  540. <Button Name='button'>Foo</Button>
  541. </Window>";
  542. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  543. var button = window.FindControl<Button>("button");
  544. Assert.Equal("Foo", button.Content);
  545. }
  546. }
  547. [Fact(Skip =
  548. @"Doesn't work with Portable.xaml, it's working in different creation order -
  549. Handled in test 'Control_Is_Added_To_Parent_Before_Final_EndInit'
  550. do we need it?")]
  551. public void Control_Is_Added_To_Parent_Before_Properties_Are_Set()
  552. {
  553. using (UnitTestApplication.Start(TestServices.StyledWindow))
  554. {
  555. var xaml = @"
  556. <Window xmlns='https://github.com/avaloniaui'
  557. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  558. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  559. <local:InitializationOrderTracker Width='100'/>
  560. </Window>";
  561. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  562. var tracker = (InitializationOrderTracker)window.Content;
  563. var attached = tracker.Order.IndexOf("AttachedToLogicalTree");
  564. var widthChanged = tracker.Order.IndexOf("Property Width Changed");
  565. Assert.NotEqual(-1, attached);
  566. Assert.NotEqual(-1, widthChanged);
  567. Assert.True(attached < widthChanged);
  568. }
  569. }
  570. [Fact]
  571. public void Control_Is_Added_To_Parent_Before_Final_EndInit()
  572. {
  573. using (UnitTestApplication.Start(TestServices.StyledWindow))
  574. {
  575. var xaml = @"
  576. <Window xmlns='https://github.com/avaloniaui'
  577. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  578. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  579. <local:InitializationOrderTracker Width='100'/>
  580. </Window>";
  581. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  582. var tracker = (InitializationOrderTracker)window.Content;
  583. var attached = tracker.Order.IndexOf("AttachedToLogicalTree");
  584. var endInit = tracker.Order.IndexOf("EndInit 0");
  585. Assert.NotEqual(-1, attached);
  586. Assert.NotEqual(-1, endInit);
  587. Assert.True(attached < endInit);
  588. }
  589. }
  590. [Fact]
  591. public void All_Properties_Are_Set_Before_Final_EndInit()
  592. {
  593. using (UnitTestApplication.Start(TestServices.StyledWindow))
  594. {
  595. var xaml = @"
  596. <Window xmlns='https://github.com/avaloniaui'
  597. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  598. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  599. <Window.Styles>
  600. <Style Selector='local|InitializationOrderTracker'>
  601. <Style.Resources>
  602. <x:Double x:Key='Double'>100</x:Double>
  603. </Style.Resources>
  604. </Style>
  605. </Window.Styles>
  606. <local:InitializationOrderTracker Width='100' Height='{DynamicResource Double}'
  607. Tag='{Binding Height, RelativeSource={RelativeSource Self}}' />
  608. </Window>";
  609. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  610. var tracker = (InitializationOrderTracker)window.Content;
  611. //ensure binding is set and operational first
  612. Assert.Equal(100.0, tracker.Tag);
  613. Assert.Equal("EndInit 0", tracker.Order.Last());
  614. }
  615. }
  616. [Fact]
  617. public void BeginInit_Matches_EndInit()
  618. {
  619. using (UnitTestApplication.Start(TestServices.StyledWindow))
  620. {
  621. var xaml = @"
  622. <Window xmlns='https://github.com/avaloniaui'
  623. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  624. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  625. <local:InitializationOrderTracker />
  626. </Window>";
  627. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  628. var tracker = (InitializationOrderTracker)window.Content;
  629. Assert.Equal(0, tracker.InitState);
  630. }
  631. }
  632. [Fact]
  633. public void DeferedXamlLoader_Should_Preserve_NamespacesContext()
  634. {
  635. var xaml =
  636. @"<ContentControl xmlns='https://github.com/avaloniaui'
  637. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  638. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  639. <ContentControl.ContentTemplate>
  640. <DataTemplate>
  641. <TextBlock Tag='{x:Static local:NonControl.StringProperty}'/>
  642. </DataTemplate>
  643. </ContentControl.ContentTemplate>
  644. </ContentControl>";
  645. var contentControl = AvaloniaXamlLoader.Parse<ContentControl>(xaml);
  646. var template = contentControl.ContentTemplate;
  647. Assert.NotNull(template);
  648. var txt = (TextBlock)template.Build(null);
  649. Assert.Equal((object)NonControl.StringProperty, txt.Tag);
  650. }
  651. [Fact]
  652. public void Binding_To_List_AvaloniaProperty_Is_Operational()
  653. {
  654. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  655. {
  656. var xaml = @"
  657. <Window xmlns='https://github.com/avaloniaui'>
  658. <ListBox Items='{Binding Items}' SelectedItems='{Binding SelectedItems}'/>
  659. </Window>";
  660. var window = AvaloniaXamlLoader.Parse<Window>(xaml);
  661. var listBox = (ListBox)window.Content;
  662. var vm = new SelectedItemsViewModel()
  663. {
  664. Items = new string[] { "foo", "bar", "baz" }
  665. };
  666. window.DataContext = vm;
  667. Assert.Equal(vm.Items, listBox.Items);
  668. Assert.Equal(vm.SelectedItems, listBox.SelectedItems);
  669. }
  670. }
  671. private class SelectedItemsViewModel : INotifyPropertyChanged
  672. {
  673. public string[] Items { get; set; }
  674. public event PropertyChangedEventHandler PropertyChanged;
  675. private IList _selectedItems = new AvaloniaList<string>();
  676. public IList SelectedItems
  677. {
  678. get { return _selectedItems; }
  679. set
  680. {
  681. _selectedItems = value;
  682. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItems)));
  683. }
  684. }
  685. }
  686. }
  687. }