BasicTests.cs 26 KB

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