CompiledBindingExtensionTests.cs 90 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277
  1. #nullable enable
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using System.ComponentModel;
  7. using System.Globalization;
  8. using System.Linq;
  9. using System.Reactive.Subjects;
  10. using System.Runtime.CompilerServices;
  11. using System.Threading.Tasks;
  12. using System.Xml;
  13. using Avalonia.Collections;
  14. using Avalonia.Controls;
  15. using Avalonia.Controls.Presenters;
  16. using Avalonia.Controls.Templates;
  17. using Avalonia.Data;
  18. using Avalonia.Data.Converters;
  19. using Avalonia.Data.Core;
  20. using Avalonia.Input;
  21. using Avalonia.Markup.Data;
  22. using Avalonia.Markup.Xaml.MarkupExtensions;
  23. using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
  24. using Avalonia.Markup.Xaml.Templates;
  25. using Avalonia.Media;
  26. using Avalonia.Media.Immutable;
  27. using Avalonia.Metadata;
  28. using Avalonia.UnitTests;
  29. using Xunit;
  30. namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
  31. {
  32. public class CompiledBindingExtensionTests
  33. {
  34. static CompiledBindingExtensionTests()
  35. {
  36. RuntimeHelpers.RunClassConstructor(typeof(RelativeSource).TypeHandle);
  37. }
  38. [Fact]
  39. public void ResolvesClrPropertyBasedOnDataContextType()
  40. {
  41. using (UnitTestApplication.Start(TestServices.StyledWindow))
  42. {
  43. var xaml = @"
  44. <Window xmlns='https://github.com/avaloniaui'
  45. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  46. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  47. x:DataType='local:TestDataContext'>
  48. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  49. </Window>";
  50. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  51. var textBlock = window.GetControl<TextBlock>("textBlock");
  52. var dataContext = new TestDataContext
  53. {
  54. StringProperty = "foobar"
  55. };
  56. window.DataContext = dataContext;
  57. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  58. }
  59. }
  60. [Fact]
  61. public void ResolvesClrPropertyBasedOnDataContextType_InterfaceInheritance()
  62. {
  63. using (UnitTestApplication.Start(TestServices.StyledWindow))
  64. {
  65. var xaml = @"
  66. <Window xmlns='https://github.com/avaloniaui'
  67. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  68. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  69. x:DataType='local:IHasPropertyDerived'>
  70. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  71. </Window>";
  72. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  73. var textBlock = window.GetControl<TextBlock>("textBlock");
  74. var dataContext = new TestDataContext
  75. {
  76. StringProperty = "foobar"
  77. };
  78. window.DataContext = dataContext;
  79. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  80. }
  81. }
  82. [Fact]
  83. public void ResolvesPathPassedByProperty()
  84. {
  85. using (UnitTestApplication.Start(TestServices.StyledWindow))
  86. {
  87. var xaml = @"
  88. <Window xmlns='https://github.com/avaloniaui'
  89. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  90. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  91. x:DataType='local:TestDataContext'>
  92. <TextBlock Text='{CompiledBinding Path=StringProperty}' Name='textBlock' />
  93. </Window>";
  94. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  95. var textBlock = window.GetControl<TextBlock>("textBlock");
  96. var dataContext = new TestDataContext
  97. {
  98. StringProperty = "foobar"
  99. };
  100. window.DataContext = dataContext;
  101. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  102. }
  103. }
  104. [Fact]
  105. public void ResolvesPathPassedByPropertyWithInnerItemTemplate()
  106. {
  107. using (UnitTestApplication.Start(TestServices.StyledWindow))
  108. {
  109. var xaml = @"
  110. <Window xmlns='https://github.com/avaloniaui'
  111. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  112. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  113. x:DataType='local:TestDataContext'>
  114. <ItemsControl Name='itemsControl' ItemsSource='{CompiledBinding Path=ListProperty}'>
  115. <ItemsControl.ItemTemplate>
  116. <DataTemplate>
  117. <TextBlock />
  118. </DataTemplate>
  119. </ItemsControl.ItemTemplate>
  120. </ItemsControl>
  121. </Window>";
  122. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  123. var textBlock = window.GetControl<ItemsControl>("itemsControl");
  124. var dataContext = new TestDataContext
  125. {
  126. ListProperty =
  127. {
  128. "Hello"
  129. }
  130. };
  131. window.DataContext = dataContext;
  132. Assert.Equal(dataContext.ListProperty, textBlock.ItemsSource);
  133. }
  134. }
  135. [Fact]
  136. public void ResolvesStaticClrPropertyBased()
  137. {
  138. using (UnitTestApplication.Start(TestServices.StyledWindow))
  139. {
  140. var xaml = @"
  141. <Window xmlns='https://github.com/avaloniaui'
  142. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  143. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  144. x:DataType='local:TestDataContext'>
  145. <TextBlock Text='{CompiledBinding StaticProperty}' Name='textBlock' />
  146. </Window>";
  147. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  148. var textBlock = window.GetControl<TextBlock>("textBlock");
  149. textBlock.DataContext = new TestDataContext();
  150. Assert.Equal(TestDataContext.StaticProperty, textBlock.Text);
  151. }
  152. }
  153. [Fact]
  154. public void ResolvesDataTypeFromBindingProperty()
  155. {
  156. using (UnitTestApplication.Start(TestServices.StyledWindow))
  157. {
  158. var xaml = @"
  159. <Window xmlns='https://github.com/avaloniaui'
  160. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  161. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  162. <TextBlock Text='{CompiledBinding StringProperty, DataType=local:TestDataContext}' Name='textBlock' />
  163. </Window>";
  164. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  165. var textBlock = window.GetControl<TextBlock>("textBlock");
  166. var dataContext = new TestDataContext
  167. {
  168. StringProperty = "foobar"
  169. };
  170. window.DataContext = dataContext;
  171. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  172. }
  173. }
  174. [Fact]
  175. public void ResolvesDataTypeFromBindingProperty_TypeExtension()
  176. {
  177. using (UnitTestApplication.Start(TestServices.StyledWindow))
  178. {
  179. var xaml = @"
  180. <Window xmlns='https://github.com/avaloniaui'
  181. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  182. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  183. <TextBlock Text='{CompiledBinding StringProperty, DataType={x:Type local:TestDataContext}}' Name='textBlock' />
  184. </Window>";
  185. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  186. var textBlock = window.GetControl<TextBlock>("textBlock");
  187. var dataContext = new TestDataContext
  188. {
  189. StringProperty = "foobar"
  190. };
  191. window.DataContext = dataContext;
  192. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  193. }
  194. }
  195. [Fact]
  196. public void ResolvesStreamTaskBindingCorrectly()
  197. {
  198. using (UnitTestApplication.Start(TestServices.StyledWindow))
  199. {
  200. var xaml = @"
  201. <Window xmlns='https://github.com/avaloniaui'
  202. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  203. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  204. x:DataType='local:TestDataContext'>
  205. <TextBlock Text='{CompiledBinding TaskProperty^}' Name='textBlock' />
  206. </Window>";
  207. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  208. var textBlock = window.GetControl<TextBlock>("textBlock");
  209. var dataContext = new TestDataContext
  210. {
  211. TaskProperty = Task.FromResult("foobar")
  212. };
  213. window.DataContext = dataContext;
  214. Assert.Equal(dataContext.TaskProperty.Result, textBlock.Text);
  215. }
  216. }
  217. [Fact]
  218. public void ResolvesStreamObservableBindingCorrectly()
  219. {
  220. using (UnitTestApplication.Start(TestServices.StyledWindow))
  221. {
  222. var xaml = @"
  223. <Window xmlns='https://github.com/avaloniaui'
  224. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  225. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  226. x:DataType='local:TestDataContext'>
  227. <TextBlock Text='{CompiledBinding ObservableProperty^}' Name='textBlock' />
  228. </Window>";
  229. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  230. var textBlock = window.GetControl<TextBlock>("textBlock");
  231. DelayedBinding.ApplyBindings(textBlock);
  232. var subject = new Subject<string>();
  233. var dataContext = new TestDataContext
  234. {
  235. ObservableProperty = subject
  236. };
  237. window.DataContext = dataContext;
  238. subject.OnNext("foobar");
  239. Assert.Equal("foobar", textBlock.Text);
  240. }
  241. }
  242. [Fact]
  243. public void ResolvesIndexerBindingCorrectly()
  244. {
  245. using (UnitTestApplication.Start(TestServices.StyledWindow))
  246. {
  247. var xaml = @"
  248. <Window xmlns='https://github.com/avaloniaui'
  249. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  250. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  251. x:DataType='local:TestDataContext'>
  252. <TextBlock Text='{CompiledBinding ListProperty[3]}' Name='textBlock' />
  253. </Window>";
  254. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  255. var textBlock = window.GetControl<TextBlock>("textBlock");
  256. var dataContext = new TestDataContext
  257. {
  258. ListProperty = { "A", "B", "C", "D", "E" }
  259. };
  260. window.DataContext = dataContext;
  261. Assert.Equal(dataContext.ListProperty[3], textBlock.Text);
  262. }
  263. }
  264. [Fact]
  265. public void ResolvesArrayIndexerBindingCorrectly()
  266. {
  267. using (UnitTestApplication.Start(TestServices.StyledWindow))
  268. {
  269. var xaml = @"
  270. <Window xmlns='https://github.com/avaloniaui'
  271. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  272. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  273. x:DataType='local:TestDataContext'>
  274. <TextBlock Text='{CompiledBinding ArrayProperty[3]}' Name='textBlock' />
  275. </Window>";
  276. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  277. var textBlock = window.GetControl<TextBlock>("textBlock");
  278. var dataContext = new TestDataContext
  279. {
  280. ArrayProperty = new[] { "A", "B", "C", "D", "E" }
  281. };
  282. window.DataContext = dataContext;
  283. Assert.Equal(dataContext.ArrayProperty[3], textBlock.Text);
  284. }
  285. }
  286. [Fact]
  287. public void ResolvesObservableIndexerBindingCorrectly()
  288. {
  289. using (UnitTestApplication.Start(TestServices.StyledWindow))
  290. {
  291. var xaml = @"
  292. <Window xmlns='https://github.com/avaloniaui'
  293. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  294. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  295. x:DataType='local:TestDataContext'>
  296. <TextBlock Text='{CompiledBinding ObservableCollectionProperty[3]}' Name='textBlock' />
  297. </Window>";
  298. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  299. var textBlock = window.GetControl<TextBlock>("textBlock");
  300. var dataContext = new TestDataContext
  301. {
  302. ObservableCollectionProperty = { "A", "B", "C", "D", "E" }
  303. };
  304. window.DataContext = dataContext;
  305. Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text);
  306. dataContext.ObservableCollectionProperty[3] = "New Value";
  307. Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text);
  308. }
  309. }
  310. [Fact]
  311. public void InfersCompiledBindingDataContextFromDataContextBinding()
  312. {
  313. using (UnitTestApplication.Start(TestServices.StyledWindow))
  314. {
  315. var xaml = @"
  316. <Window xmlns='https://github.com/avaloniaui'
  317. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  318. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  319. x:DataType='local:TestDataContext'>
  320. <TextBlock DataContext='{CompiledBinding StringProperty}' Text='{CompiledBinding}' Name='textBlock' />
  321. </Window>";
  322. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  323. var textBlock = window.GetControl<TextBlock>("textBlock");
  324. window.ApplyTemplate();
  325. window.Presenter!.ApplyTemplate();
  326. var dataContext = new TestDataContext
  327. {
  328. StringProperty = "A"
  329. };
  330. window.DataContext = dataContext;
  331. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  332. }
  333. }
  334. [Fact]
  335. public void ResolvesNonIntegerIndexerBindingCorrectly()
  336. {
  337. using (UnitTestApplication.Start(TestServices.StyledWindow))
  338. {
  339. var xaml = @"
  340. <Window xmlns='https://github.com/avaloniaui'
  341. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  342. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  343. x:DataType='local:TestDataContext'>
  344. <TextBlock Text='{CompiledBinding NonIntegerIndexerProperty[Test]}' Name='textBlock' />
  345. </Window>";
  346. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  347. var textBlock = window.GetControl<TextBlock>("textBlock");
  348. var dataContext = new TestDataContext();
  349. dataContext.NonIntegerIndexerProperty["Test"] = "Initial Value";
  350. window.DataContext = dataContext;
  351. Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text);
  352. dataContext.NonIntegerIndexerProperty["Test"] = "New Value";
  353. Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text);
  354. }
  355. }
  356. [Fact]
  357. public void ResolvesNonIntegerIndexerBindingFromParentInterfaceCorrectly()
  358. {
  359. using (UnitTestApplication.Start(TestServices.StyledWindow))
  360. {
  361. var xaml = @"
  362. <Window xmlns='https://github.com/avaloniaui'
  363. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  364. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  365. x:DataType='local:TestDataContext'>
  366. <TextBlock Text='{CompiledBinding NonIntegerIndexerInterfaceProperty[Test]}' Name='textBlock' />
  367. </Window>";
  368. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  369. var textBlock = window.GetControl<TextBlock>("textBlock");
  370. var dataContext = new TestDataContext();
  371. dataContext.NonIntegerIndexerInterfaceProperty["Test"] = "Initial Value";
  372. window.DataContext = dataContext;
  373. Assert.Equal(dataContext.NonIntegerIndexerInterfaceProperty["Test"], textBlock.Text);
  374. dataContext.NonIntegerIndexerInterfaceProperty["Test"] = "New Value";
  375. Assert.Equal(dataContext.NonIntegerIndexerInterfaceProperty["Test"], textBlock.Text);
  376. }
  377. }
  378. [Fact]
  379. public void InfersDataTemplateTypeFromDataTypeProperty()
  380. {
  381. using (UnitTestApplication.Start(TestServices.StyledWindow))
  382. {
  383. var xaml = @"
  384. <Window xmlns='https://github.com/avaloniaui'
  385. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  386. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  387. x:DataType='local:TestDataContext'>
  388. <Window.DataTemplates>
  389. <DataTemplate DataType='{x:Type x:String}'>
  390. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  391. </DataTemplate>
  392. </Window.DataTemplates>
  393. <ContentControl Name='target' Content='{CompiledBinding StringProperty}' />
  394. </Window>";
  395. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  396. var target = window.GetControl<ContentControl>("target");
  397. var dataContext = new TestDataContext();
  398. dataContext.StringProperty = "Initial Value";
  399. window.DataContext = dataContext;
  400. window.ApplyTemplate();
  401. target.ApplyTemplate();
  402. target.Presenter!.UpdateChild();
  403. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
  404. }
  405. }
  406. [Fact]
  407. public void ThrowsOnUninferrableLooseDataTemplateNoDataTypeWithCompiledBindingPath()
  408. {
  409. using (UnitTestApplication.Start(TestServices.StyledWindow))
  410. {
  411. var xaml = @"
  412. <Window xmlns='https://github.com/avaloniaui'
  413. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  414. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  415. x:DataType='local:TestDataContext'>
  416. <Window.DataTemplates>
  417. <DataTemplate>
  418. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  419. </DataTemplate>
  420. </Window.DataTemplates>
  421. <ContentControl Name='target' Content='{CompiledBinding}' />
  422. </Window>";
  423. Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  424. }
  425. }
  426. [Fact]
  427. public void ThrowsOnUninferrableDataTypeFromNonCompiledDataContextBindingWithCompiledBindingPath()
  428. {
  429. using (UnitTestApplication.Start(TestServices.StyledWindow))
  430. {
  431. var xaml = @"
  432. <Window xmlns='https://github.com/avaloniaui'
  433. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  434. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  435. x:DataType='local:TestDataContext'>
  436. <ContentControl Name='target' DataContext='{Binding}'>
  437. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  438. </ContentControl>
  439. </Window>";
  440. Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  441. }
  442. }
  443. [Fact]
  444. public void ReportsMultipleErrorsOnDataContextAndBindingPathErrors()
  445. {
  446. using (UnitTestApplication.Start(TestServices.StyledWindow))
  447. {
  448. var xaml = @"
  449. <Window xmlns='https://github.com/avaloniaui'
  450. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  451. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  452. <ContentControl Content='{CompiledBinding NoDataContext}'
  453. Tag='{CompiledBinding NonExistentProp, DataType=local:TestDataContext}'
  454. Height='{CompiledBinding invalid.}' />
  455. </Window>";
  456. var ex = Assert.Throws<AggregateException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  457. Assert.Collection(
  458. ex.InnerExceptions,
  459. inner => Assert.IsAssignableFrom<XmlException>(inner),
  460. inner => Assert.IsAssignableFrom<XmlException>(inner),
  461. inner => Assert.IsAssignableFrom<XmlException>(inner));
  462. }
  463. }
  464. [Fact]
  465. public void InfersDataTemplateTypeFromParentCollectionItemsType()
  466. {
  467. using (UnitTestApplication.Start(TestServices.StyledWindow))
  468. {
  469. var xaml = @"
  470. <Window xmlns='https://github.com/avaloniaui'
  471. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  472. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  473. x:DataType='local:TestDataContext'>
  474. <ItemsControl ItemsSource='{CompiledBinding ListProperty}' Name='target'>
  475. <ItemsControl.ItemTemplate>
  476. <DataTemplate>
  477. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  478. </DataTemplate>
  479. </ItemsControl.ItemTemplate>
  480. </ItemsControl>
  481. </Window>";
  482. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  483. var target = window.GetControl<ItemsControl>("target");
  484. var dataContext = new TestDataContext();
  485. dataContext.ListProperty.Add("Test");
  486. window.DataContext = dataContext;
  487. window.ApplyTemplate();
  488. target.ApplyTemplate();
  489. target.Presenter!.ApplyTemplate();
  490. Assert.Equal(dataContext.ListProperty[0], (string?)((ContentPresenter)target.Presenter.Panel!.Children[0]).Content);
  491. }
  492. }
  493. [Fact]
  494. public void InfersDataTemplateTypeFromParentDataGridItemsType()
  495. {
  496. using (UnitTestApplication.Start(TestServices.StyledWindow))
  497. {
  498. var window = (Window)AvaloniaRuntimeXamlLoader.Load(@"
  499. <Window xmlns='https://github.com/avaloniaui'
  500. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  501. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  502. x:DataType='local:TestDataContext'>
  503. <local:DataGridLikeControl Items='{CompiledBinding ListProperty}' Name='target'>
  504. <local:DataGridLikeControl.Columns>
  505. <local:DataGridLikeColumn Binding='{CompiledBinding Length}'>
  506. <local:DataGridLikeColumn.Template>
  507. <DataTemplate>
  508. <TextBlock Text='{CompiledBinding Length}' />
  509. </DataTemplate>
  510. </local:DataGridLikeColumn.Template>
  511. </local:DataGridLikeColumn>
  512. </local:DataGridLikeControl.Columns>
  513. </local:DataGridLikeControl>
  514. </Window>");
  515. var target = window.GetControl<DataGridLikeControl>("target");
  516. var column = target.Columns.Single();
  517. var dataContext = new TestDataContext();
  518. dataContext.ListProperty.Add("Test");
  519. window.DataContext = dataContext;
  520. window.ApplyTemplate();
  521. target.ApplyTemplate();
  522. // Assert DataGridLikeColumn.Binding data type.
  523. var compiledPath = ((CompiledBindingExtension)column.Binding!).Path;
  524. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  525. Assert.Equal(typeof(int), node.Property.PropertyType);
  526. // Assert DataGridLikeColumn.Template data type by evaluating the template.
  527. var firstItem = dataContext.ListProperty[0];
  528. var textBlockFromTemplate = (TextBlock)column.Template!.Build(firstItem)!;
  529. textBlockFromTemplate.DataContext = firstItem;
  530. Assert.Equal(firstItem.Length.ToString(), textBlockFromTemplate.Text);
  531. }
  532. }
  533. [Fact]
  534. public void ExplicitDataTypeStillWorksOnDataGridLikeControls()
  535. {
  536. using (UnitTestApplication.Start(TestServices.StyledWindow))
  537. {
  538. var window = (Window)AvaloniaRuntimeXamlLoader.Load(@"
  539. <Window xmlns='https://github.com/avaloniaui'
  540. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  541. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  542. x:DataType='local:TestDataContext'>
  543. <local:DataGridLikeControl Name='target'>
  544. <local:DataGridLikeControl.Columns>
  545. <local:DataGridLikeColumn Binding='{CompiledBinding Length}' x:DataType='x:String'>
  546. <local:DataGridLikeColumn.Template>
  547. <DataTemplate x:DataType='x:String'>
  548. <TextBlock Text='{CompiledBinding Length}' />
  549. </DataTemplate>
  550. </local:DataGridLikeColumn.Template>
  551. </local:DataGridLikeColumn>
  552. </local:DataGridLikeControl.Columns>
  553. </local:DataGridLikeControl>
  554. </Window>");
  555. var target = window.GetControl<DataGridLikeControl>("target");
  556. var column = target.Columns.Single();
  557. var dataContext = new TestDataContext();
  558. dataContext.ListProperty.Add("Test");
  559. target.Items = dataContext.ListProperty;
  560. window.ApplyTemplate();
  561. target.ApplyTemplate();
  562. // Assert DataGridLikeColumn.Binding data type.
  563. var compiledPath = ((CompiledBindingExtension)column.Binding!).Path;
  564. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  565. Assert.Equal(typeof(int), node.Property.PropertyType);
  566. // Assert DataGridLikeColumn.Template data type by evaluating the template.
  567. var firstItem = dataContext.ListProperty[0];
  568. var textBlockFromTemplate = (TextBlock)column.Template!.Build(firstItem)!;
  569. textBlockFromTemplate.DataContext = firstItem;
  570. Assert.Equal(firstItem.Length.ToString(), textBlockFromTemplate.Text);
  571. }
  572. }
  573. [Fact]
  574. public void ThrowsOnUninferrableDataTemplateInItemsControlWithoutItemsBinding()
  575. {
  576. using (UnitTestApplication.Start(TestServices.StyledWindow))
  577. {
  578. var xaml = @"
  579. <Window xmlns='https://github.com/avaloniaui'
  580. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  581. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  582. x:DataType='local:TestDataContext'>
  583. <ItemsControl Name='target'>
  584. <ItemsControl.DataTemplates>
  585. <DataTemplate>
  586. <TextBlock Text='{CompiledBinding Property}' Name='textBlock' />
  587. </DataTemplate>
  588. </ItemsControl.DataTemplates>
  589. </ItemsControl>
  590. </Window>";
  591. Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  592. }
  593. }
  594. [Fact]
  595. public void IgnoresDataTemplateTypeFromDataTypePropertyIfXDataTypeDefined()
  596. {
  597. using (UnitTestApplication.Start(TestServices.StyledWindow))
  598. {
  599. var xaml = @"
  600. <Window xmlns='https://github.com/avaloniaui'
  601. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  602. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  603. <Window.DataTemplates>
  604. <DataTemplate DataType='local:TestDataContextBaseClass' x:DataType='local:TestDataContext'>
  605. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  606. </DataTemplate>
  607. </Window.DataTemplates>
  608. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  609. </Window>";
  610. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  611. var target = window.GetControl<ContentControl>("target");
  612. var dataContext = new TestDataContext();
  613. dataContext.StringProperty = "Initial Value";
  614. window.DataContext = dataContext;
  615. window.ApplyTemplate();
  616. target.ApplyTemplate();
  617. target.Presenter!.UpdateChild();
  618. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
  619. }
  620. }
  621. [Fact]
  622. public void InfersCustomDataTemplateBasedOnAttribute()
  623. {
  624. using (UnitTestApplication.Start(TestServices.StyledWindow))
  625. {
  626. var xaml = @"
  627. <Window xmlns='https://github.com/avaloniaui'
  628. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  629. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  630. <Window.DataTemplates>
  631. <local:CustomDataTemplate FancyDataType='local:TestDataContext'>
  632. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  633. </local:CustomDataTemplate>
  634. </Window.DataTemplates>
  635. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  636. </Window>";
  637. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  638. var target = window.GetControl<ContentControl>("target");
  639. var dataContext = new TestDataContext();
  640. dataContext.StringProperty = "Initial Value";
  641. window.DataContext = dataContext;
  642. window.ApplyTemplate();
  643. target.ApplyTemplate();
  644. target.Presenter!.UpdateChild();
  645. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
  646. }
  647. }
  648. [Fact]
  649. public void InfersCustomDataTemplateBasedOnAttributeFromBaseClass()
  650. {
  651. using (UnitTestApplication.Start(TestServices.StyledWindow))
  652. {
  653. var xaml = @"
  654. <Window xmlns='https://github.com/avaloniaui'
  655. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  656. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  657. <Window.DataTemplates>
  658. <local:CustomDataTemplateInherit FancyDataType='local:TestDataContext'>
  659. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  660. </local:CustomDataTemplateInherit>
  661. </Window.DataTemplates>
  662. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  663. </Window>";
  664. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  665. var target = window.GetControl<ContentControl>("target");
  666. var dataContext = new TestDataContext();
  667. dataContext.StringProperty = "Initial Value";
  668. window.DataContext = dataContext;
  669. window.ApplyTemplate();
  670. target.ApplyTemplate();
  671. target.Presenter!.UpdateChild();
  672. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
  673. }
  674. }
  675. [Fact]
  676. public void ResolvesElementNameBinding()
  677. {
  678. using (UnitTestApplication.Start(TestServices.StyledWindow))
  679. {
  680. var xaml = @"
  681. <Window xmlns='https://github.com/avaloniaui'
  682. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  683. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  684. x:DataType='local:TestDataContext'>
  685. <StackPanel>
  686. <TextBlock Text='{CompiledBinding StringProperty}' x:Name='text' />
  687. <TextBlock Text='{CompiledBinding #text.Text}' x:Name='text2' />
  688. </StackPanel>
  689. </Window>";
  690. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  691. var textBlock = window.GetControl<TextBlock>("text2");
  692. var dataContext = new TestDataContext
  693. {
  694. StringProperty = "foobar"
  695. };
  696. window.DataContext = dataContext;
  697. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  698. }
  699. }
  700. [Fact]
  701. public void ResolvesElementNameBindingFromLongForm()
  702. {
  703. using (UnitTestApplication.Start(TestServices.StyledWindow))
  704. {
  705. var xaml = @"
  706. <Window xmlns='https://github.com/avaloniaui'
  707. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  708. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  709. x:DataType='local:TestDataContext'>
  710. <StackPanel>
  711. <TextBlock Text='{CompiledBinding StringProperty}' x:Name='text' />
  712. <TextBlock Text='{CompiledBinding Text, ElementName=text}' x:Name='text2' />
  713. </StackPanel>
  714. </Window>";
  715. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  716. var textBlock = window.GetControl<TextBlock>("text2");
  717. var dataContext = new TestDataContext
  718. {
  719. StringProperty = "foobar"
  720. };
  721. window.DataContext = dataContext;
  722. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  723. }
  724. }
  725. [Fact]
  726. public void ResolvesElementNameBindingFromLongFormWithoutPath()
  727. {
  728. using (UnitTestApplication.Start(TestServices.StyledWindow))
  729. {
  730. var xaml = @"
  731. <Window xmlns='https://github.com/avaloniaui'
  732. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  733. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  734. x:DataType='local:TestDataContext'>
  735. <StackPanel>
  736. <TextBlock Text='{CompiledBinding StringProperty}' x:Name='text' />
  737. <TextBlock Text='{CompiledBinding ElementName=text}' x:Name='text2' />
  738. </StackPanel>
  739. </Window>";
  740. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  741. var textBlock = window.GetControl<TextBlock>("text2");
  742. Assert.Equal("Avalonia.Controls.TextBlock", textBlock.Text);
  743. }
  744. }
  745. [Fact]
  746. public void ResolvesRelativeSourceBindingLongForm()
  747. {
  748. using (UnitTestApplication.Start(TestServices.StyledWindow))
  749. {
  750. var xaml = @"
  751. <Window xmlns='https://github.com/avaloniaui'
  752. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  753. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  754. x:DataType='local:TestDataContext'
  755. Title='test'>
  756. <TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType=Window}}' x:Name='text'/>
  757. </Window>";
  758. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  759. var target = window.GetControl<TextBlock>("text");
  760. window.ApplyTemplate();
  761. window.Presenter!.ApplyTemplate();
  762. target.ApplyTemplate();
  763. Assert.Equal("test", target.Text);
  764. }
  765. }
  766. [Fact]
  767. public void ResolvesRelativeSourceBindingEvenLongerForm()
  768. {
  769. using (UnitTestApplication.Start(TestServices.StyledWindow))
  770. {
  771. var xaml = @"
  772. <Window xmlns='https://github.com/avaloniaui'
  773. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  774. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  775. x:DataType='local:TestDataContext'
  776. Title='test'>
  777. <TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}' x:Name='text'/>
  778. </Window>";
  779. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  780. var target = window.GetControl<TextBlock>("text");
  781. window.ApplyTemplate();
  782. window.Presenter!.ApplyTemplate();
  783. target.ApplyTemplate();
  784. //Assert.Equal("test", target.Text);
  785. }
  786. }
  787. [Fact]
  788. public void ResolvesRelativeSourceBindingFromTemplate()
  789. {
  790. using (UnitTestApplication.Start(TestServices.StyledWindow))
  791. {
  792. var xaml = @"
  793. <ContentControl xmlns='https://github.com/avaloniaui'
  794. Focusable='True'>
  795. <ContentControl.Styles>
  796. <Style Selector='ContentControl'>
  797. <Setter Property='Template'>
  798. <ControlTemplate>
  799. <ContentPresenter Focusable='{CompiledBinding !Focusable, RelativeSource={RelativeSource TemplatedParent}}' />
  800. </ControlTemplate>
  801. </Setter>
  802. </Style>
  803. </ContentControl.Styles>
  804. </ContentControl>";
  805. var contentControl = AvaloniaRuntimeXamlLoader.Parse<ContentControl>(xaml);
  806. contentControl.DataContext = new TestDataContext(); // should be ignored
  807. contentControl.Measure(new Size(10, 10));
  808. var result = contentControl.GetTemplateChildren().OfType<ContentPresenter>().First();
  809. Assert.Equal(false, result.Focusable);
  810. }
  811. }
  812. [Fact]
  813. public void ResolvesRelativeSourceBindingFromStyleSelector()
  814. {
  815. using (UnitTestApplication.Start(TestServices.StyledWindow))
  816. {
  817. var xaml = @"
  818. <TextBox xmlns='https://github.com/avaloniaui'
  819. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  820. InnerLeftContent='Hello'>
  821. <TextBox.Styles>
  822. <Style Selector='TextBox'>
  823. <Setter Property='Template'>
  824. <ControlTemplate>
  825. <StackPanel>
  826. <ContentPresenter x:Name='Content' />
  827. <TextPresenter x:Name='PART_TextPresenter' />
  828. </StackPanel>
  829. </ControlTemplate>
  830. </Setter>
  831. <Style Selector='^ /template/ ContentPresenter#Content'>
  832. <Setter Property='Content' Value='{CompiledBinding InnerLeftContent, RelativeSource={RelativeSource TemplatedParent}}' />
  833. </Style>
  834. </Style>
  835. </TextBox.Styles>
  836. </TextBox>";
  837. var textBox = AvaloniaRuntimeXamlLoader.Parse<TextBox>(xaml);
  838. textBox.DataContext = new TestDataContext(); // should be ignored
  839. textBox.Measure(new Size(10, 10));
  840. var result = textBox.GetTemplateChildren().OfType<ContentPresenter>().First();
  841. Assert.Equal(textBox.InnerLeftContent, result.Content);
  842. }
  843. }
  844. [Fact]
  845. public void Binds_To_TemplatedParent_From_Non_Control()
  846. {
  847. using (UnitTestApplication.Start(TestServices.StyledWindow))
  848. {
  849. var xaml = @"
  850. <Window xmlns='https://github.com/avaloniaui'
  851. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  852. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
  853. <Button Name='button'>
  854. <Button.Template>
  855. <ControlTemplate>
  856. <Grid>
  857. <Grid.ColumnDefinitions>
  858. <ColumnDefinition Width='{CompiledBinding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}'/>
  859. </Grid.ColumnDefinitions>
  860. </Grid>
  861. </ControlTemplate>
  862. </Button.Template>
  863. </Button>
  864. </Window>";
  865. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  866. var button = window.FindControl<Button>("button");
  867. button.Tag = new GridLength(5, GridUnitType.Star);
  868. window.ApplyTemplate();
  869. button.ApplyTemplate();
  870. Assert.Equal(button.Tag, button.GetTemplateChildren().OfType<Grid>().First().ColumnDefinitions[0].Width);
  871. }
  872. }
  873. [Fact]
  874. public void ResolvesElementNameInTemplate()
  875. {
  876. using (UnitTestApplication.Start(TestServices.StyledWindow))
  877. {
  878. var xaml = @"
  879. <ContentControl xmlns='https://github.com/avaloniaui'
  880. Content='Hello'>
  881. <ContentControl.Styles>
  882. <Style Selector='ContentControl'>
  883. <Setter Property='Template'>
  884. <ControlTemplate>
  885. <Panel>
  886. <TextBox Name='InnerTextBox' Text='Hello' />
  887. <ContentPresenter Content='{CompiledBinding Text, ElementName=InnerTextBox}' />
  888. </Panel>
  889. </ControlTemplate>
  890. </Setter>
  891. </Style>
  892. </ContentControl.Styles>
  893. </ContentControl>";
  894. var contentControl = AvaloniaRuntimeXamlLoader.Parse<ContentControl>(xaml);
  895. contentControl.Measure(new Size(10, 10));
  896. var result = contentControl.GetTemplateChildren().OfType<ContentPresenter>().First();
  897. Assert.Equal("Hello", result.Content);
  898. }
  899. }
  900. [Fact]
  901. public void Binds_To_Source()
  902. {
  903. using (UnitTestApplication.Start(TestServices.StyledWindow))
  904. {
  905. var xaml = @"
  906. <Window xmlns='https://github.com/avaloniaui'
  907. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  908. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  909. x:DataType='local:TestDataContext'
  910. Title='test'>
  911. <TextBlock Text='{CompiledBinding Length, Source=Test}' x:Name='text'/>
  912. </Window>";
  913. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  914. var target = window.GetControl<TextBlock>("text");
  915. window.ApplyTemplate();
  916. window.Presenter!.ApplyTemplate();
  917. target.ApplyTemplate();
  918. Assert.Equal("Test".Length.ToString(), target.Text);
  919. }
  920. }
  921. [Fact]
  922. public void Binds_To_Source_StaticResource()
  923. {
  924. using (UnitTestApplication.Start(TestServices.StyledWindow))
  925. {
  926. var xaml = @"
  927. <Window xmlns='https://github.com/avaloniaui'
  928. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  929. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  930. x:CompileBindings='True'>
  931. <Window.Resources>
  932. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  933. </Window.Resources>
  934. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  935. </Window>";
  936. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  937. var textBlock = window.GetControl<TextBlock>("textBlock");
  938. Assert.Equal("foobar", textBlock.Text);
  939. }
  940. }
  941. [Fact]
  942. public void Binds_To_Source_StaticResource1()
  943. {
  944. using (UnitTestApplication.Start(TestServices.StyledWindow))
  945. {
  946. var xaml = @"
  947. <Window xmlns='https://github.com/avaloniaui'
  948. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  949. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  950. x:CompileBindings='True'>
  951. <Window.Resources>
  952. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  953. <x:String x:Key='otherObjectKey'>test</x:String>
  954. </Window.Resources>
  955. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  956. </Window>";
  957. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  958. var textBlock = window.GetControl<TextBlock>("textBlock");
  959. Assert.Equal("foobar", textBlock.Text);
  960. }
  961. }
  962. [Fact]
  963. public void Binds_To_Source_StaticResource_In_ResourceDictionary()
  964. {
  965. using (UnitTestApplication.Start(TestServices.StyledWindow))
  966. {
  967. var xaml = @"
  968. <Window xmlns='https://github.com/avaloniaui'
  969. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  970. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  971. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  972. <Window.Resources>
  973. <ResourceDictionary>
  974. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  975. </ResourceDictionary>
  976. </Window.Resources>
  977. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  978. </Window>";
  979. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  980. var textBlock = window.GetControl<TextBlock>("textBlock");
  981. Assert.Equal("foobar", textBlock.Text);
  982. }
  983. }
  984. [Fact]
  985. public void Binds_To_Source_StaticResource_In_ResourceDictionary1()
  986. {
  987. using (UnitTestApplication.Start(TestServices.StyledWindow))
  988. {
  989. var xaml = @"
  990. <Window xmlns='https://github.com/avaloniaui'
  991. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  992. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  993. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  994. <Window.Resources>
  995. <ResourceDictionary>
  996. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  997. <x:String x:Key='otherObjectKey'>test</x:String>
  998. </ResourceDictionary>
  999. </Window.Resources>
  1000. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  1001. </Window>";
  1002. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1003. var textBlock = window.GetControl<TextBlock>("textBlock");
  1004. Assert.Equal("foobar", textBlock.Text);
  1005. }
  1006. }
  1007. [Fact]
  1008. public void Binds_To_Source_xStatic()
  1009. {
  1010. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1011. {
  1012. var xaml = @"
  1013. <Window xmlns='https://github.com/avaloniaui'
  1014. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1015. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1016. x:CompileBindings='True'>
  1017. <ContentControl Name='contentControl' Content='{Binding Color, Source={x:Static Brushes.Red}}'/>
  1018. </Window>";
  1019. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1020. var contentControl = window.GetControl<ContentControl>("contentControl");
  1021. Assert.Equal(Brushes.Red.Color, contentControl.Content);
  1022. }
  1023. }
  1024. [Fact]
  1025. public void CompilesBindingWhenRequested()
  1026. {
  1027. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1028. {
  1029. var xaml = @"
  1030. <Window xmlns='https://github.com/avaloniaui'
  1031. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1032. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1033. x:DataType='local:TestDataContext'
  1034. x:CompileBindings='true'>
  1035. <TextBlock Text='{Binding StringProperty}' Name='textBlock' />
  1036. </Window>";
  1037. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1038. var textBlock = window.GetControl<TextBlock>("textBlock");
  1039. var dataContext = new TestDataContext
  1040. {
  1041. StringProperty = "foobar"
  1042. };
  1043. window.DataContext = dataContext;
  1044. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  1045. }
  1046. }
  1047. [Fact]
  1048. public void ThrowsOnInvalidBindingPathOnCompiledBindingEnabledViaDirective()
  1049. {
  1050. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1051. {
  1052. var xaml = @"
  1053. <Window xmlns='https://github.com/avaloniaui'
  1054. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1055. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1056. x:DataType='local:TestDataContext'
  1057. x:CompileBindings='true'>
  1058. <TextBlock Text='{Binding InvalidPath}' Name='textBlock' />
  1059. </Window>";
  1060. Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  1061. }
  1062. }
  1063. [Fact]
  1064. public void SupportParentInPath()
  1065. {
  1066. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1067. {
  1068. var xaml = @"
  1069. <Window xmlns='https://github.com/avaloniaui'
  1070. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1071. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1072. Title='foo'>
  1073. <ContentControl Content='{CompiledBinding $parent.Title}' Name='contentControl' />
  1074. </Window>";
  1075. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1076. var contentControl = window.GetControl<ContentControl>("contentControl");
  1077. Assert.Equal("foo", contentControl.Content);
  1078. }
  1079. }
  1080. [Fact]
  1081. public void SupportConverterWithParameter()
  1082. {
  1083. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1084. {
  1085. var xaml = @"
  1086. <Window xmlns='https://github.com/avaloniaui'
  1087. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1088. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1089. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  1090. <TextBlock Name='textBlock' Text='{Binding StringProperty, Converter={x:Static local:AppendConverter.Instance}, ConverterParameter=Bar}'/>
  1091. </Window>";
  1092. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1093. var textBlock = window.GetControl<TextBlock>("textBlock");
  1094. window.DataContext = new TestDataContext() { StringProperty = "Foo" };
  1095. Assert.Equal($"Foo+Bar+{CultureInfo.CurrentCulture}", textBlock.Text);
  1096. }
  1097. }
  1098. [Fact]
  1099. public void SupportConverterWithCulture()
  1100. {
  1101. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1102. {
  1103. var xaml = @"
  1104. <Window xmlns='https://github.com/avaloniaui'
  1105. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1106. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1107. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  1108. <TextBlock Name='textBlock' Text='{Binding StringProperty, Converter={x:Static local:AppendConverter.Instance}, ConverterCulture=ar-SA}'/>
  1109. </Window>";
  1110. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1111. var textBlock = window.GetControl<TextBlock>("textBlock");
  1112. window.DataContext = new TestDataContext() { StringProperty = "Foo" };
  1113. Assert.Equal($"Foo++ar-SA", textBlock.Text);
  1114. }
  1115. }
  1116. [Fact]
  1117. public void ThrowsOnInvalidCompileBindingsDirective()
  1118. {
  1119. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1120. {
  1121. var xaml = @"
  1122. <Window xmlns='https://github.com/avaloniaui'
  1123. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1124. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1125. x:DataType='local:TestDataContext'
  1126. x:CompileBindings='notabool'>
  1127. </Window>";
  1128. Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  1129. }
  1130. }
  1131. [Fact]
  1132. public void SupportCastToTypeInExpression()
  1133. {
  1134. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1135. {
  1136. var xaml = @"
  1137. <Window xmlns='https://github.com/avaloniaui'
  1138. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1139. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1140. x:DataType='local:TestDataContext'>
  1141. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
  1142. </Window>";
  1143. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1144. var contentControl = window.GetControl<ContentControl>("contentControl");
  1145. var dataContext = new TestDataContext();
  1146. window.DataContext = dataContext;
  1147. Assert.Equal(dataContext, contentControl.Content);
  1148. }
  1149. }
  1150. [Fact]
  1151. public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
  1152. {
  1153. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1154. {
  1155. var xaml = @"
  1156. <Window xmlns='https://github.com/avaloniaui'
  1157. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1158. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1159. x:DataType='local:TestDataContext'>
  1160. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
  1161. </Window>";
  1162. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1163. var contentControl = window.GetControl<ContentControl>("contentControl");
  1164. var dataContext = "foo";
  1165. window.DataContext = dataContext;
  1166. Assert.Equal(null, contentControl.Content);
  1167. }
  1168. }
  1169. [Fact]
  1170. public void SupportCastToTypeInExpressionWithProperty()
  1171. {
  1172. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1173. {
  1174. var xaml = @"
  1175. <Window xmlns='https://github.com/avaloniaui'
  1176. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1177. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1178. x:DataType='local:TestDataContext'>
  1179. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
  1180. </Window>";
  1181. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1182. var contentControl = window.GetControl<ContentControl>("contentControl");
  1183. var dataContext = new TestDataContext
  1184. {
  1185. StringProperty = "foobar"
  1186. };
  1187. window.DataContext = dataContext;
  1188. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  1189. }
  1190. }
  1191. [Fact]
  1192. public void SupportCastToTypeInExpressionWithProperty1()
  1193. {
  1194. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1195. {
  1196. var xaml = @"
  1197. <Window xmlns='https://github.com/avaloniaui'
  1198. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1199. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1200. x:DataType='local:TestDataContext'>
  1201. <ContentControl Content='{CompiledBinding $parent.DataContext(local:TestDataContext).StringProperty}' Name='contentControl' />
  1202. </Window>";
  1203. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1204. var contentControl = window.GetControl<ContentControl>("contentControl");
  1205. var dataContext = new TestDataContext
  1206. {
  1207. StringProperty = "foobar"
  1208. };
  1209. window.DataContext = dataContext;
  1210. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  1211. }
  1212. }
  1213. [Fact]
  1214. public void SupportCastToTypeInExpressionWithPropertyIndexer()
  1215. {
  1216. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1217. {
  1218. var xaml = @"
  1219. <Window xmlns='https://github.com/avaloniaui'
  1220. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1221. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1222. x:DataType='local:TestDataContext'>
  1223. <ContentControl Content='{CompiledBinding ((local:TestData)ObjectsArrayProperty[0]).StringProperty}' Name='contentControl' />
  1224. </Window>";
  1225. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1226. var contentControl = window.GetControl<ContentControl>("contentControl");
  1227. var data = new TestData()
  1228. {
  1229. StringProperty = "Foo"
  1230. };
  1231. var dataContext = new TestDataContext
  1232. {
  1233. ObjectsArrayProperty = new object[] { data }
  1234. };
  1235. window.DataContext = dataContext;
  1236. Assert.Equal(data.StringProperty, contentControl.Content);
  1237. }
  1238. }
  1239. [Fact]
  1240. public void SupportCastToTypeInExpressionWithProperty_DifferentTypeEvaluatesToNull()
  1241. {
  1242. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1243. {
  1244. var xaml = @"
  1245. <Window xmlns='https://github.com/avaloniaui'
  1246. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1247. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1248. x:DataType='local:TestDataContext'>
  1249. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
  1250. </Window>";
  1251. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1252. var contentControl = window.GetControl<ContentControl>("contentControl");
  1253. var dataContext = new TestDataContext
  1254. {
  1255. StringProperty = "foobar"
  1256. };
  1257. window.DataContext = dataContext;
  1258. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  1259. window.DataContext = "foo";
  1260. Assert.Equal(null, contentControl.Content);
  1261. }
  1262. }
  1263. [Fact]
  1264. public void SupportsEmptyPath()
  1265. {
  1266. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1267. {
  1268. var xaml = @"
  1269. <Window xmlns='https://github.com/avaloniaui'
  1270. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1271. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1272. x:DataType='local:TestDataContext'>
  1273. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  1274. </Window>";
  1275. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1276. var textBlock = window.GetControl<TextBlock>("textBlock");
  1277. var dataContext = new TestDataContext
  1278. {
  1279. StringProperty = "foobar"
  1280. };
  1281. window.DataContext = dataContext;
  1282. Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
  1283. }
  1284. }
  1285. [Fact]
  1286. public void SupportsEmptyPathWithStringFormat()
  1287. {
  1288. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1289. {
  1290. var xaml = @"
  1291. <Window xmlns='https://github.com/avaloniaui'
  1292. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1293. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1294. x:DataType='local:TestDataContext'>
  1295. <TextBlock Text='{CompiledBinding StringFormat=bar-\{0\}}' Name='textBlock' />
  1296. </Window>";
  1297. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1298. var textBlock = window.GetControl<TextBlock>("textBlock");
  1299. var dataContext = new TestDataContext
  1300. {
  1301. StringProperty = "foobar"
  1302. };
  1303. window.DataContext = dataContext;
  1304. Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
  1305. }
  1306. }
  1307. [Fact]
  1308. public void SupportsDotPath()
  1309. {
  1310. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1311. {
  1312. var xaml = @"
  1313. <Window xmlns='https://github.com/avaloniaui'
  1314. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1315. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1316. x:DataType='local:TestDataContext'>
  1317. <TextBlock Text='{CompiledBinding .}' Name='textBlock' />
  1318. </Window>";
  1319. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1320. var textBlock = window.GetControl<TextBlock>("textBlock");
  1321. var dataContext = new TestDataContext
  1322. {
  1323. StringProperty = "foobar"
  1324. };
  1325. window.DataContext = dataContext;
  1326. Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
  1327. }
  1328. }
  1329. [Fact]
  1330. public void SupportsExplicitDotPathWithStringFormat()
  1331. {
  1332. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1333. {
  1334. var xaml = @"
  1335. <Window xmlns='https://github.com/avaloniaui'
  1336. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1337. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1338. x:DataType='local:TestDataContext'>
  1339. <TextBlock Text='{CompiledBinding Path=., StringFormat=bar-\{0\}}' Name='textBlock' />
  1340. </Window>";
  1341. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1342. var textBlock = window.GetControl<TextBlock>("textBlock");
  1343. var dataContext = new TestDataContext
  1344. {
  1345. StringProperty = "foobar"
  1346. };
  1347. window.DataContext = dataContext;
  1348. Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
  1349. }
  1350. }
  1351. [Fact]
  1352. public void SupportCastToTypeInExpressionWithProperty_ExplicitPropertyCast()
  1353. {
  1354. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1355. {
  1356. var xaml = @"
  1357. <Window xmlns='https://github.com/avaloniaui'
  1358. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1359. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'>
  1360. <ContentControl Content='{CompiledBinding $parent.((local:IHasExplicitProperty)DataContext).ExplicitProperty}' Name='contentControl' />
  1361. </Window>";
  1362. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1363. var contentControl = window.GetControl<ContentControl>("contentControl");
  1364. var dataContext = new TestDataContext();
  1365. window.DataContext = dataContext;
  1366. Assert.Equal(((IHasExplicitProperty)dataContext).ExplicitProperty, contentControl.Content);
  1367. }
  1368. }
  1369. [Fact]
  1370. public void Binds_To_Self()
  1371. {
  1372. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1373. {
  1374. var xaml = @"
  1375. <Window xmlns='https://github.com/avaloniaui'
  1376. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1377. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1378. x:DataType='local:TestDataContext'>
  1379. <TextBlock Name='textBlock' Text='{CompiledBinding $self}' />
  1380. </Window>";
  1381. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1382. var textBlock = window.GetControl<TextBlock>("textBlock");
  1383. window.ApplyTemplate();
  1384. window.Presenter!.ApplyTemplate();
  1385. Assert.Equal("Avalonia.Controls.TextBlock", textBlock.Text);
  1386. }
  1387. }
  1388. [Fact]
  1389. public void Binds_To_Self_Without_DataType()
  1390. {
  1391. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1392. {
  1393. var xaml = @"
  1394. <Window xmlns='https://github.com/avaloniaui'
  1395. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1396. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  1397. <TextBlock Name='textBlock' Text='{CompiledBinding $self.Name}' />
  1398. </Window>";
  1399. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1400. var textBlock = window.GetControl<TextBlock>("textBlock");
  1401. window.ApplyTemplate();
  1402. window.Presenter!.ApplyTemplate();
  1403. Assert.Equal(textBlock.Name, textBlock.Text);
  1404. }
  1405. }
  1406. [Fact]
  1407. public void Binds_To_Self_In_Style()
  1408. {
  1409. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1410. {
  1411. var xaml = @"
  1412. <Window xmlns='https://github.com/avaloniaui'
  1413. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  1414. <Window.Styles>
  1415. <Style Selector='Button'>
  1416. <Setter Property='IsVisible' Value='{CompiledBinding $self.IsEnabled}' />
  1417. </Style>
  1418. </Window.Styles>
  1419. <Button Name='button' />
  1420. </Window>";
  1421. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1422. var button = window.GetControl<Button>("button");
  1423. window.ApplyTemplate();
  1424. window.Presenter!.ApplyTemplate();
  1425. Assert.True(button.IsVisible);
  1426. button.IsEnabled = false;
  1427. Assert.False(button.IsVisible);
  1428. }
  1429. }
  1430. [Fact]
  1431. public void Binds_To_RelativeSource_Self()
  1432. {
  1433. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1434. {
  1435. var xaml = @"
  1436. <Window xmlns='https://github.com/avaloniaui'
  1437. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1438. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1439. x:DataType='local:TestDataContext'>
  1440. <TextBlock Name='textBlock' Text='{CompiledBinding RelativeSource={RelativeSource Self}}' />
  1441. </Window>";
  1442. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1443. var textBlock = window.GetControl<TextBlock>("textBlock");
  1444. window.ApplyTemplate();
  1445. window.Presenter!.ApplyTemplate();
  1446. Assert.Equal("Avalonia.Controls.TextBlock", textBlock.Text);
  1447. }
  1448. }
  1449. [Fact]
  1450. public void SupportsMethodBindingAsDelegate()
  1451. {
  1452. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1453. {
  1454. var xaml = @"
  1455. <Window xmlns='https://github.com/avaloniaui'
  1456. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1457. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1458. x:DataType='local:MethodDataContext'>
  1459. <StackPanel>
  1460. <ContentControl Content='{CompiledBinding Action}' Name='action' />
  1461. <ContentControl Content='{CompiledBinding Func}' Name='func' />
  1462. <ContentControl Content='{CompiledBinding Action16}' Name='action16' />
  1463. <ContentControl Content='{CompiledBinding Func16}' Name='func16' />
  1464. <ContentControl Content='{CompiledBinding CustomDelegateTypeVoid}' Name='customvoid' />
  1465. <ContentControl Content='{CompiledBinding CustomDelegateTypeInt}' Name='customint' />
  1466. </StackPanel>
  1467. </Window>";
  1468. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1469. window.DataContext = new MethodDataContext();
  1470. Assert.IsAssignableFrom(typeof(Action), window.GetControl<ContentControl>("action").Content);
  1471. Assert.IsAssignableFrom(typeof(Func<int>), window.GetControl<ContentControl>("func").Content);
  1472. Assert.IsAssignableFrom(typeof(Action<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.GetControl<ContentControl>("action16").Content);
  1473. Assert.IsAssignableFrom(typeof(Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.GetControl<ContentControl>("func16").Content);
  1474. Assert.True(typeof(Delegate).IsAssignableFrom(window.GetControl<ContentControl>("customvoid").Content!.GetType()));
  1475. Assert.True(typeof(Delegate).IsAssignableFrom(window.GetControl<ContentControl>("customint").Content!.GetType()));
  1476. }
  1477. }
  1478. [Fact]
  1479. public void Binding_Method_To_Command_Works()
  1480. {
  1481. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1482. {
  1483. var xaml = @"
  1484. <Window xmlns='https://github.com/avaloniaui'
  1485. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1486. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1487. x:DataType='local:MethodAsCommandDataContext'>
  1488. <Button Name='button' Command='{CompiledBinding Method}'/>
  1489. </Window>";
  1490. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1491. var button = window.GetControl<Button>("button");
  1492. var vm = new MethodAsCommandDataContext();
  1493. button.DataContext = vm;
  1494. window.ApplyTemplate();
  1495. Assert.NotNull(button.Command);
  1496. PerformClick(button);
  1497. Assert.Equal("Called", vm.Value);
  1498. }
  1499. }
  1500. [Fact]
  1501. public void Binding_Method_With_Parameter_To_Command_Works()
  1502. {
  1503. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1504. {
  1505. var xaml = @"
  1506. <Window xmlns='https://github.com/avaloniaui'
  1507. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1508. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1509. x:DataType='local:MethodAsCommandDataContext'>
  1510. <Button Name='button' Command='{CompiledBinding Method1}' CommandParameter='5'/>
  1511. </Window>";
  1512. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1513. var button = window.GetControl<Button>("button");
  1514. var vm = new MethodAsCommandDataContext();
  1515. button.DataContext = vm;
  1516. window.ApplyTemplate();
  1517. Assert.NotNull(button.Command);
  1518. PerformClick(button);
  1519. Assert.Equal("Called 5", vm.Value);
  1520. }
  1521. }
  1522. [Fact]
  1523. public void Binding_Method_To_TextBlock_Text_Works()
  1524. {
  1525. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1526. {
  1527. var xaml = @"
  1528. <Window xmlns='https://github.com/avaloniaui'
  1529. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1530. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1531. x:DataType='local:MethodAsCommandDataContext'>
  1532. <TextBlock Name='textBlock' Text='{CompiledBinding Method}'/>
  1533. </Window>";
  1534. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1535. var textBlock = window.GetControl<TextBlock>("textBlock");
  1536. var vm = new MethodAsCommandDataContext();
  1537. textBlock.DataContext = vm;
  1538. window.ApplyTemplate();
  1539. Assert.NotNull(textBlock.Text);
  1540. }
  1541. }
  1542. [Theory]
  1543. [InlineData(null, "Not called")]
  1544. [InlineData("A", "Do A")]
  1545. public void Binding_Method_With_Parameter_To_Command_CanExecute(object commandParameter, string result)
  1546. {
  1547. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1548. {
  1549. var xaml = @"
  1550. <Window xmlns='https://github.com/avaloniaui'
  1551. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1552. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1553. x:DataType='local:MethodAsCommandDataContext'>
  1554. <Button Name='button' Command='{CompiledBinding Do}' CommandParameter='{CompiledBinding Parameter, Mode=OneTime}'/>
  1555. </Window>";
  1556. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1557. var button = window.GetControl<Button>("button");
  1558. var vm = new MethodAsCommandDataContext()
  1559. {
  1560. Parameter = commandParameter
  1561. };
  1562. button.DataContext = vm;
  1563. window.ApplyTemplate();
  1564. Assert.NotNull(button.Command);
  1565. PerformClick(button);
  1566. Assert.Equal(vm.Value, result);
  1567. }
  1568. }
  1569. [Fact]
  1570. public void Binding_Method_With_Parameter_To_Command_CanExecute_DependsOn()
  1571. {
  1572. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1573. {
  1574. var xaml = @"
  1575. <Window xmlns='https://github.com/avaloniaui'
  1576. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1577. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1578. x:DataType='local:MethodAsCommandDataContext'>
  1579. <Button Name='button' Command='{CompiledBinding Do}'/>
  1580. </Window>";
  1581. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1582. var button = window.GetControl<Button>("button");
  1583. var vm = new MethodAsCommandDataContext()
  1584. {
  1585. Parameter = null,
  1586. };
  1587. button.DataContext = vm;
  1588. window.ApplyTemplate();
  1589. Assert.NotNull(button.Command);
  1590. Assert.Equal(button.IsEffectivelyEnabled, false);
  1591. vm.Parameter = true;
  1592. Threading.Dispatcher.UIThread.RunJobs();
  1593. Assert.Equal(button.IsEffectivelyEnabled, true);
  1594. }
  1595. }
  1596. [Fact]
  1597. public void ResolvesDataTypeForAssignBinding()
  1598. {
  1599. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1600. {
  1601. var xaml = @"
  1602. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1603. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1604. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1605. x:DataType='local:TestDataContext'
  1606. X='{CompiledBinding StringProperty}' />";
  1607. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
  1608. var compiledPath = ((CompiledBindingExtension)control.X!).Path;
  1609. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1610. Assert.Equal(typeof(string), node.Property.PropertyType);
  1611. }
  1612. }
  1613. [Fact]
  1614. public void ResolvesDataTypeForAssignBinding_FromBindingProperty()
  1615. {
  1616. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1617. {
  1618. var xaml = @"
  1619. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1620. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1621. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1622. X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
  1623. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
  1624. var compiledPath = ((CompiledBindingExtension)control.X!).Path;
  1625. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1626. Assert.Equal(typeof(string), node.Property.PropertyType);
  1627. }
  1628. }
  1629. [Fact]
  1630. public void Uses_RuntimeLoader_Configuration_To_Enabled_Compiled()
  1631. {
  1632. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1633. {
  1634. var xaml = @"
  1635. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1636. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1637. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1638. X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
  1639. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml),
  1640. new RuntimeXamlLoaderConfiguration { UseCompiledBindingsByDefault = true });
  1641. var compiledPath = ((CompiledBindingExtension)control.X!).Path;
  1642. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1643. Assert.Equal(typeof(string), node.Property.PropertyType);
  1644. }
  1645. }
  1646. [Fact]
  1647. public void Should_Bind_To_Nested_Generic_Property()
  1648. {
  1649. // See https://github.com/AvaloniaUI/Avalonia/issues/10485
  1650. // This code works fine with SRE, and test is passing, but it fails on Cecil.
  1651. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1652. {
  1653. var xaml = @"
  1654. <Window xmlns='https://github.com/avaloniaui'
  1655. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1656. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1657. x:DataType='local:TestDataContext'
  1658. x:CompileBindings='True'>
  1659. <ComboBox x:Name='comboBox' ItemsSource='{Binding GenericProperty}' SelectedItem='{Binding GenericProperty.CurrentItem}' />
  1660. </Window>";
  1661. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1662. var comboBox = window.GetControl<ComboBox>("comboBox");
  1663. var dataContext = new TestDataContext();
  1664. dataContext.GenericProperty.Add(123);
  1665. dataContext.GenericProperty.CurrentItem = 123;
  1666. window.DataContext = dataContext;
  1667. Assert.Equal(123, comboBox.SelectedItem);
  1668. }
  1669. }
  1670. [Theory]
  1671. [InlineData(false)]
  1672. [InlineData(true)]
  1673. public void Should_Use_StringFormat_Without_Braces(bool compileBindings)
  1674. {
  1675. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1676. {
  1677. var xaml = $@"
  1678. <Window xmlns='https://github.com/avaloniaui'
  1679. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1680. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1681. x:DataType='local:TestDataContext'
  1682. x:CompileBindings='{compileBindings}'>
  1683. <TextBlock Name='textBlock' Text='{{Binding DecimalValue, StringFormat=c2}}'/>
  1684. </Window>";
  1685. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1686. var textBlock = window.GetControl<TextBlock>("textBlock");
  1687. var dataContext = new TestDataContext();
  1688. window.DataContext = dataContext;
  1689. Assert.Equal(string.Format("{0:c2}", TestDataContext.ExpectedDecimal)
  1690. , textBlock.GetValue(TextBlock.TextProperty));
  1691. }
  1692. }
  1693. [Theory]
  1694. [InlineData(true)]
  1695. [InlineData(false)]
  1696. public void Should_Negate_Boolean_Value(bool value)
  1697. {
  1698. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1699. {
  1700. var xaml = $@"
  1701. <Window xmlns='https://github.com/avaloniaui'
  1702. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1703. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1704. x:DataType='local:TestDataContext'
  1705. x:CompileBindings='True'>
  1706. <TextBlock Name='textBlock' Tag='{{Binding !BoolProperty}}'/>
  1707. </Window>";
  1708. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1709. var textBlock = window.FindControl<TextBlock>("textBlock");
  1710. var dataContext = new TestDataContext { BoolProperty = value };
  1711. window.DataContext = dataContext;
  1712. var result = Assert.IsType<bool>(textBlock.Tag);
  1713. Assert.Equal(!value, result);
  1714. }
  1715. }
  1716. [Fact]
  1717. public void Can_Use_Implicit_Conversions()
  1718. {
  1719. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1720. {
  1721. var xaml = $@"
  1722. <Window xmlns='https://github.com/avaloniaui'
  1723. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1724. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1725. x:DataType='local:ImplicitConvertible'
  1726. x:CompileBindings='True'>
  1727. <TextBlock Name='textBlock'>
  1728. <TextBlock.Background>
  1729. <SolidColorBrush Color='{{Binding}}'/>
  1730. </TextBlock.Background>
  1731. </TextBlock>
  1732. </Window>";
  1733. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1734. var textBlock = window.FindControl<TextBlock>("textBlock");
  1735. var dataContext = new ImplicitConvertible("Green");
  1736. window.DataContext = dataContext;
  1737. var brush = Assert.IsType<SolidColorBrush>(textBlock.Background);
  1738. Assert.Equal(Colors.Green, brush.Color);
  1739. }
  1740. }
  1741. [Fact]
  1742. public void Can_Bind_Brush_To_Hex_String()
  1743. {
  1744. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1745. {
  1746. var xaml = $@"
  1747. <Window xmlns='https://github.com/avaloniaui'
  1748. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1749. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1750. x:DataType='local:TestData'
  1751. x:CompileBindings='True'>
  1752. <TextBlock Name='textBlock' Background='{{Binding StringProperty}}'/>
  1753. </Window>";
  1754. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1755. var textBlock = window.FindControl<TextBlock>("textBlock");
  1756. var dataContext = new TestData { StringProperty = "#ff0000" };
  1757. window.DataContext = dataContext;
  1758. var brush = Assert.IsType<ImmutableSolidColorBrush>(textBlock!.Background);
  1759. Assert.Equal(Colors.Red, brush.Color);
  1760. }
  1761. }
  1762. static void Throws(string type, Action cb)
  1763. {
  1764. try
  1765. {
  1766. cb();
  1767. }
  1768. catch (Exception e) when (e.GetType().Name == type)
  1769. {
  1770. return;
  1771. }
  1772. throw new Exception("Expected " + type);
  1773. }
  1774. static void PerformClick(Button button)
  1775. {
  1776. button.RaiseEvent(new KeyEventArgs
  1777. {
  1778. RoutedEvent = InputElement.KeyDownEvent,
  1779. Key = Key.Enter,
  1780. });
  1781. }
  1782. }
  1783. public interface INonIntegerIndexer
  1784. {
  1785. string this[string key] { get; set; }
  1786. }
  1787. public interface INonIntegerIndexerDerived : INonIntegerIndexer
  1788. { }
  1789. public interface IHasProperty
  1790. {
  1791. string? StringProperty { get; set; }
  1792. }
  1793. public interface IHasPropertyDerived : IHasProperty
  1794. { }
  1795. public interface IHasExplicitProperty
  1796. {
  1797. string ExplicitProperty { get; }
  1798. }
  1799. public class AppendConverter : IValueConverter
  1800. {
  1801. public static IValueConverter Instance { get; } = new AppendConverter();
  1802. public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
  1803. => string.Format("{0}+{1}+{2}", value, parameter, culture);
  1804. public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
  1805. => throw new NotImplementedException();
  1806. }
  1807. public class TestData
  1808. {
  1809. public string? StringProperty { get; set; }
  1810. }
  1811. public class TestDataContextBaseClass {}
  1812. public class TestDataContext : TestDataContextBaseClass, IHasPropertyDerived, IHasExplicitProperty
  1813. {
  1814. public bool BoolProperty { get; set; }
  1815. public string? StringProperty { get; set; }
  1816. public Task<string>? TaskProperty { get; set; }
  1817. public IObservable<string>? ObservableProperty { get; set; }
  1818. public ObservableCollection<string> ObservableCollectionProperty { get; set; } = new ObservableCollection<string>();
  1819. public string[]? ArrayProperty { get; set; }
  1820. public object[]? ObjectsArrayProperty { get; set; }
  1821. public List<string> ListProperty { get; set; } = new List<string>();
  1822. public NonIntegerIndexer NonIntegerIndexerProperty { get; set; } = new NonIntegerIndexer();
  1823. public INonIntegerIndexerDerived NonIntegerIndexerInterfaceProperty => NonIntegerIndexerProperty;
  1824. string IHasExplicitProperty.ExplicitProperty => "Hello";
  1825. public string ExplicitProperty => "Bye";
  1826. public static string StaticProperty => "World";
  1827. public ListItemCollectionView<int> GenericProperty { get; } = new();
  1828. public const decimal ExpectedDecimal = 15.756m;
  1829. public decimal DecimalValue { get; set; } = ExpectedDecimal;
  1830. public class NonIntegerIndexer : NotifyingBase, INonIntegerIndexerDerived
  1831. {
  1832. private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();
  1833. public string this[string key]
  1834. {
  1835. get => _storage[key];
  1836. set
  1837. {
  1838. _storage[key] = value;
  1839. RaisePropertyChanged(CommonPropertyNames.IndexerName);
  1840. }
  1841. }
  1842. }
  1843. }
  1844. public class ListItemCollectionView<T> : List<T>
  1845. {
  1846. public T? CurrentItem { get; set; }
  1847. }
  1848. public class MethodDataContext
  1849. {
  1850. public void Action() { }
  1851. public int Func() => 1;
  1852. public void Action16(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16) { }
  1853. public int Func16(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16) => i;
  1854. public void CustomDelegateTypeVoid(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16, int i17) { }
  1855. public int CustomDelegateTypeInt(int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16, int i17) => i;
  1856. }
  1857. public class MethodAsCommandDataContext : INotifyPropertyChanged
  1858. {
  1859. public event PropertyChangedEventHandler? PropertyChanged;
  1860. public string Method() => Value = "Called";
  1861. public string Method1(int i) => Value = $"Called {i}";
  1862. public string Method2(int i, int j) => Value = $"Called {i},{j}";
  1863. public string Value { get; private set; } = "Not called";
  1864. private object? _parameter;
  1865. public object? Parameter
  1866. {
  1867. get => _parameter;
  1868. set
  1869. {
  1870. if (_parameter == value)
  1871. {
  1872. return;
  1873. }
  1874. _parameter = value;
  1875. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Parameter)));
  1876. }
  1877. }
  1878. public void Do(object parameter)
  1879. {
  1880. Value = $"Do {parameter}";
  1881. }
  1882. [DependsOn(nameof(Parameter))]
  1883. public bool CanDo(object parameter)
  1884. {
  1885. return ReferenceEquals(null, Parameter) == false;
  1886. }
  1887. }
  1888. public class CustomDataTemplate : IDataTemplate
  1889. {
  1890. [DataType]
  1891. public Type? FancyDataType { get; set; }
  1892. [Content]
  1893. [TemplateContent]
  1894. public object? Content { get; set; }
  1895. public bool Match(object? data) => FancyDataType?.IsInstanceOfType(data) ?? true;
  1896. public Control? Build(object? data) => TemplateContent.Load(Content)?.Result;
  1897. }
  1898. public class CustomDataTemplateInherit : CustomDataTemplate { }
  1899. public class AssignBindingControl : Control
  1900. {
  1901. [AssignBinding] public IBinding? X { get; set; }
  1902. }
  1903. public class DataGridLikeControl : Control
  1904. {
  1905. public static readonly DirectProperty<DataGridLikeControl, IEnumerable?> ItemsProperty =
  1906. AvaloniaProperty.RegisterDirect<DataGridLikeControl, IEnumerable?>(
  1907. nameof(Items),
  1908. x => x.Items,
  1909. (x, v) => x.Items = v);
  1910. private IEnumerable? _items;
  1911. public IEnumerable? Items
  1912. {
  1913. get => _items;
  1914. set => SetAndRaise(ItemsProperty, ref _items, value);
  1915. }
  1916. public AvaloniaList<DataGridLikeColumn> Columns { get; } = new();
  1917. }
  1918. public class DataGridLikeColumn
  1919. {
  1920. [AssignBinding]
  1921. [InheritDataTypeFromItems(nameof(DataGridLikeControl.Items), AncestorType = typeof(DataGridLikeControl))]
  1922. public IBinding? Binding { get; set; }
  1923. [InheritDataTypeFromItems(nameof(DataGridLikeControl.Items), AncestorType = typeof(DataGridLikeControl))]
  1924. public IDataTemplate? Template { get; set; }
  1925. }
  1926. public class ImplicitConvertible
  1927. {
  1928. public ImplicitConvertible(string value) => Value = value;
  1929. public string Value { get; }
  1930. public static implicit operator Avalonia.Media.Color(ImplicitConvertible value)
  1931. {
  1932. return Color.Parse(value.Value);
  1933. }
  1934. }
  1935. }