CompiledBindingExtensionTests.cs 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Reactive.Subjects;
  8. using System.Runtime.CompilerServices;
  9. using System.Threading.Tasks;
  10. using Avalonia.Controls;
  11. using Avalonia.Controls.Presenters;
  12. using Avalonia.Controls.Templates;
  13. using Avalonia.Data;
  14. using Avalonia.Data.Converters;
  15. using Avalonia.Data.Core;
  16. using Avalonia.Input;
  17. using Avalonia.Markup.Data;
  18. using Avalonia.Markup.Xaml.MarkupExtensions;
  19. using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
  20. using Avalonia.Markup.Xaml.Templates;
  21. using Avalonia.Media;
  22. using Avalonia.Metadata;
  23. using Avalonia.UnitTests;
  24. using Xunit;
  25. namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
  26. {
  27. public class CompiledBindingExtensionTests
  28. {
  29. static CompiledBindingExtensionTests()
  30. {
  31. RuntimeHelpers.RunClassConstructor(typeof(RelativeSource).TypeHandle);
  32. }
  33. [Fact]
  34. public void ResolvesClrPropertyBasedOnDataContextType()
  35. {
  36. using (UnitTestApplication.Start(TestServices.StyledWindow))
  37. {
  38. var xaml = @"
  39. <Window xmlns='https://github.com/avaloniaui'
  40. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  41. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  42. x:DataType='local:TestDataContext'>
  43. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  44. </Window>";
  45. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  46. var textBlock = window.FindControl<TextBlock>("textBlock");
  47. var dataContext = new TestDataContext
  48. {
  49. StringProperty = "foobar"
  50. };
  51. window.DataContext = dataContext;
  52. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  53. }
  54. }
  55. [Fact]
  56. public void ResolvesClrPropertyBasedOnDataContextType_InterfaceInheritance()
  57. {
  58. using (UnitTestApplication.Start(TestServices.StyledWindow))
  59. {
  60. var xaml = @"
  61. <Window xmlns='https://github.com/avaloniaui'
  62. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  63. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  64. x:DataType='local:IHasPropertyDerived'>
  65. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  66. </Window>";
  67. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  68. var textBlock = window.FindControl<TextBlock>("textBlock");
  69. var dataContext = new TestDataContext
  70. {
  71. StringProperty = "foobar"
  72. };
  73. window.DataContext = dataContext;
  74. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  75. }
  76. }
  77. [Fact]
  78. public void ResolvesPathPassedByProperty()
  79. {
  80. using (UnitTestApplication.Start(TestServices.StyledWindow))
  81. {
  82. var xaml = @"
  83. <Window xmlns='https://github.com/avaloniaui'
  84. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  85. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  86. x:DataType='local:TestDataContext'>
  87. <TextBlock Text='{CompiledBinding Path=StringProperty}' Name='textBlock' />
  88. </Window>";
  89. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  90. var textBlock = window.FindControl<TextBlock>("textBlock");
  91. var dataContext = new TestDataContext
  92. {
  93. StringProperty = "foobar"
  94. };
  95. window.DataContext = dataContext;
  96. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  97. }
  98. }
  99. [Fact]
  100. public void ResolvesPathPassedByPropertyWithInnerItemTemplate()
  101. {
  102. using (UnitTestApplication.Start(TestServices.StyledWindow))
  103. {
  104. var xaml = @"
  105. <Window xmlns='https://github.com/avaloniaui'
  106. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  107. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  108. x:DataType='local:TestDataContext'>
  109. <ItemsControl Name='itemsControl' Items='{CompiledBinding Path=ListProperty}'>
  110. <ItemsControl.ItemTemplate>
  111. <DataTemplate>
  112. <TextBlock />
  113. </DataTemplate>
  114. </ItemsControl.ItemTemplate>
  115. </ItemsControl>
  116. </Window>";
  117. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  118. var textBlock = window.FindControl<ItemsControl>("itemsControl");
  119. var dataContext = new TestDataContext
  120. {
  121. ListProperty =
  122. {
  123. "Hello"
  124. }
  125. };
  126. window.DataContext = dataContext;
  127. Assert.Equal(dataContext.ListProperty, textBlock.Items);
  128. }
  129. }
  130. [Fact]
  131. public void ResolvesStaticClrPropertyBased()
  132. {
  133. using (UnitTestApplication.Start(TestServices.StyledWindow))
  134. {
  135. var xaml = @"
  136. <Window xmlns='https://github.com/avaloniaui'
  137. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  138. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  139. x:DataType='local:TestDataContext'>
  140. <TextBlock Text='{CompiledBinding StaticProperty}' Name='textBlock' />
  141. </Window>";
  142. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  143. var textBlock = window.FindControl<TextBlock>("textBlock");
  144. textBlock.DataContext = new TestDataContext();
  145. Assert.Equal(TestDataContext.StaticProperty, textBlock.Text);
  146. }
  147. }
  148. [Fact]
  149. public void ResolvesDataTypeFromBindingProperty()
  150. {
  151. using (UnitTestApplication.Start(TestServices.StyledWindow))
  152. {
  153. var xaml = @"
  154. <Window xmlns='https://github.com/avaloniaui'
  155. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  156. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  157. <TextBlock Text='{CompiledBinding StringProperty, DataType=local:TestDataContext}' Name='textBlock' />
  158. </Window>";
  159. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  160. var textBlock = window.FindControl<TextBlock>("textBlock");
  161. var dataContext = new TestDataContext
  162. {
  163. StringProperty = "foobar"
  164. };
  165. window.DataContext = dataContext;
  166. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  167. }
  168. }
  169. [Fact]
  170. public void ResolvesDataTypeFromBindingProperty_TypeExtension()
  171. {
  172. using (UnitTestApplication.Start(TestServices.StyledWindow))
  173. {
  174. var xaml = @"
  175. <Window xmlns='https://github.com/avaloniaui'
  176. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  177. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  178. <TextBlock Text='{CompiledBinding StringProperty, DataType={x:Type local:TestDataContext}}' Name='textBlock' />
  179. </Window>";
  180. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  181. var textBlock = window.FindControl<TextBlock>("textBlock");
  182. var dataContext = new TestDataContext
  183. {
  184. StringProperty = "foobar"
  185. };
  186. window.DataContext = dataContext;
  187. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  188. }
  189. }
  190. [Fact]
  191. public void ResolvesStreamTaskBindingCorrectly()
  192. {
  193. using (UnitTestApplication.Start(TestServices.StyledWindow))
  194. {
  195. var xaml = @"
  196. <Window xmlns='https://github.com/avaloniaui'
  197. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  198. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  199. x:DataType='local:TestDataContext'>
  200. <TextBlock Text='{CompiledBinding TaskProperty^}' Name='textBlock' />
  201. </Window>";
  202. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  203. var textBlock = window.FindControl<TextBlock>("textBlock");
  204. var dataContext = new TestDataContext
  205. {
  206. TaskProperty = Task.FromResult("foobar")
  207. };
  208. window.DataContext = dataContext;
  209. Assert.Equal(dataContext.TaskProperty.Result, textBlock.Text);
  210. }
  211. }
  212. [Fact]
  213. public void ResolvesStreamObservableBindingCorrectly()
  214. {
  215. using (UnitTestApplication.Start(TestServices.StyledWindow))
  216. {
  217. var xaml = @"
  218. <Window xmlns='https://github.com/avaloniaui'
  219. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  220. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  221. x:DataType='local:TestDataContext'>
  222. <TextBlock Text='{CompiledBinding ObservableProperty^}' Name='textBlock' />
  223. </Window>";
  224. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  225. var textBlock = window.FindControl<TextBlock>("textBlock");
  226. DelayedBinding.ApplyBindings(textBlock);
  227. var subject = new Subject<string>();
  228. var dataContext = new TestDataContext
  229. {
  230. ObservableProperty = subject
  231. };
  232. window.DataContext = dataContext;
  233. subject.OnNext("foobar");
  234. Assert.Equal("foobar", textBlock.Text);
  235. }
  236. }
  237. [Fact]
  238. public void ResolvesIndexerBindingCorrectly()
  239. {
  240. using (UnitTestApplication.Start(TestServices.StyledWindow))
  241. {
  242. var xaml = @"
  243. <Window xmlns='https://github.com/avaloniaui'
  244. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  245. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  246. x:DataType='local:TestDataContext'>
  247. <TextBlock Text='{CompiledBinding ListProperty[3]}' Name='textBlock' />
  248. </Window>";
  249. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  250. var textBlock = window.FindControl<TextBlock>("textBlock");
  251. var dataContext = new TestDataContext
  252. {
  253. ListProperty = { "A", "B", "C", "D", "E" }
  254. };
  255. window.DataContext = dataContext;
  256. Assert.Equal(dataContext.ListProperty[3], textBlock.Text);
  257. }
  258. }
  259. [Fact]
  260. public void ResolvesArrayIndexerBindingCorrectly()
  261. {
  262. using (UnitTestApplication.Start(TestServices.StyledWindow))
  263. {
  264. var xaml = @"
  265. <Window xmlns='https://github.com/avaloniaui'
  266. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  267. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  268. x:DataType='local:TestDataContext'>
  269. <TextBlock Text='{CompiledBinding ArrayProperty[3]}' Name='textBlock' />
  270. </Window>";
  271. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  272. var textBlock = window.FindControl<TextBlock>("textBlock");
  273. var dataContext = new TestDataContext
  274. {
  275. ArrayProperty = new[] { "A", "B", "C", "D", "E" }
  276. };
  277. window.DataContext = dataContext;
  278. Assert.Equal(dataContext.ArrayProperty[3], textBlock.Text);
  279. }
  280. }
  281. [Fact]
  282. public void ResolvesObservableIndexerBindingCorrectly()
  283. {
  284. using (UnitTestApplication.Start(TestServices.StyledWindow))
  285. {
  286. var xaml = @"
  287. <Window xmlns='https://github.com/avaloniaui'
  288. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  289. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  290. x:DataType='local:TestDataContext'>
  291. <TextBlock Text='{CompiledBinding ObservableCollectionProperty[3]}' Name='textBlock' />
  292. </Window>";
  293. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  294. var textBlock = window.FindControl<TextBlock>("textBlock");
  295. var dataContext = new TestDataContext
  296. {
  297. ObservableCollectionProperty = { "A", "B", "C", "D", "E" }
  298. };
  299. window.DataContext = dataContext;
  300. Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text);
  301. dataContext.ObservableCollectionProperty[3] = "New Value";
  302. Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text);
  303. }
  304. }
  305. [Fact]
  306. public void InfersCompiledBindingDataContextFromDataContextBinding()
  307. {
  308. using (UnitTestApplication.Start(TestServices.StyledWindow))
  309. {
  310. var xaml = @"
  311. <Window xmlns='https://github.com/avaloniaui'
  312. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  313. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  314. x:DataType='local:TestDataContext'>
  315. <TextBlock DataContext='{CompiledBinding StringProperty}' Text='{CompiledBinding}' Name='textBlock' />
  316. </Window>";
  317. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  318. var textBlock = window.FindControl<TextBlock>("textBlock");
  319. window.ApplyTemplate();
  320. window.Presenter.ApplyTemplate();
  321. var dataContext = new TestDataContext
  322. {
  323. StringProperty = "A"
  324. };
  325. window.DataContext = dataContext;
  326. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  327. }
  328. }
  329. [Fact]
  330. public void ResolvesNonIntegerIndexerBindingCorrectly()
  331. {
  332. using (UnitTestApplication.Start(TestServices.StyledWindow))
  333. {
  334. var xaml = @"
  335. <Window xmlns='https://github.com/avaloniaui'
  336. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  337. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  338. x:DataType='local:TestDataContext'>
  339. <TextBlock Text='{CompiledBinding NonIntegerIndexerProperty[Test]}' Name='textBlock' />
  340. </Window>";
  341. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  342. var textBlock = window.FindControl<TextBlock>("textBlock");
  343. var dataContext = new TestDataContext();
  344. dataContext.NonIntegerIndexerProperty["Test"] = "Initial Value";
  345. window.DataContext = dataContext;
  346. Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text);
  347. dataContext.NonIntegerIndexerProperty["Test"] = "New Value";
  348. Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text);
  349. }
  350. }
  351. [Fact]
  352. public void ResolvesNonIntegerIndexerBindingFromParentInterfaceCorrectly()
  353. {
  354. using (UnitTestApplication.Start(TestServices.StyledWindow))
  355. {
  356. var xaml = @"
  357. <Window xmlns='https://github.com/avaloniaui'
  358. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  359. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  360. x:DataType='local:TestDataContext'>
  361. <TextBlock Text='{CompiledBinding NonIntegerIndexerInterfaceProperty[Test]}' Name='textBlock' />
  362. </Window>";
  363. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  364. var textBlock = window.FindControl<TextBlock>("textBlock");
  365. var dataContext = new TestDataContext();
  366. dataContext.NonIntegerIndexerInterfaceProperty["Test"] = "Initial Value";
  367. window.DataContext = dataContext;
  368. Assert.Equal(dataContext.NonIntegerIndexerInterfaceProperty["Test"], textBlock.Text);
  369. dataContext.NonIntegerIndexerInterfaceProperty["Test"] = "New Value";
  370. Assert.Equal(dataContext.NonIntegerIndexerInterfaceProperty["Test"], textBlock.Text);
  371. }
  372. }
  373. [Fact]
  374. public void InfersDataTemplateTypeFromDataTypeProperty()
  375. {
  376. using (UnitTestApplication.Start(TestServices.StyledWindow))
  377. {
  378. var xaml = @"
  379. <Window xmlns='https://github.com/avaloniaui'
  380. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  381. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  382. x:DataType='local:TestDataContext'>
  383. <Window.DataTemplates>
  384. <DataTemplate DataType='{x:Type x:String}'>
  385. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  386. </DataTemplate>
  387. </Window.DataTemplates>
  388. <ContentControl Name='target' Content='{CompiledBinding StringProperty}' />
  389. </Window>";
  390. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  391. var target = window.FindControl<ContentControl>("target");
  392. var dataContext = new TestDataContext();
  393. dataContext.StringProperty = "Initial Value";
  394. window.DataContext = dataContext;
  395. window.ApplyTemplate();
  396. target.ApplyTemplate();
  397. ((ContentPresenter)target.Presenter).UpdateChild();
  398. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
  399. }
  400. }
  401. [Fact]
  402. public void ThrowsOnUninferrableLooseDataTemplateNoDataTypeWithCompiledBindingPath()
  403. {
  404. using (UnitTestApplication.Start(TestServices.StyledWindow))
  405. {
  406. var xaml = @"
  407. <Window xmlns='https://github.com/avaloniaui'
  408. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  409. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  410. x:DataType='local:TestDataContext'>
  411. <Window.DataTemplates>
  412. <DataTemplate>
  413. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  414. </DataTemplate>
  415. </Window.DataTemplates>
  416. <ContentControl Name='target' Content='{CompiledBinding}' />
  417. </Window>";
  418. ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  419. }
  420. }
  421. [Fact]
  422. public void ThrowsOnUninferrableDataTypeFromNonCompiledDataContextBindingWithCompiledBindingPath()
  423. {
  424. using (UnitTestApplication.Start(TestServices.StyledWindow))
  425. {
  426. var xaml = @"
  427. <Window xmlns='https://github.com/avaloniaui'
  428. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  429. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  430. x:DataType='local:TestDataContext'>
  431. <ContentControl Name='target' DataContext='{Binding}'>
  432. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  433. </ContentControl>
  434. </Window>";
  435. ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  436. }
  437. }
  438. [Fact]
  439. public void InfersDataTemplateTypeFromParentCollectionItemsType()
  440. {
  441. using (UnitTestApplication.Start(TestServices.StyledWindow))
  442. {
  443. var xaml = @"
  444. <Window xmlns='https://github.com/avaloniaui'
  445. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  446. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  447. x:DataType='local:TestDataContext'>
  448. <ItemsControl Items='{CompiledBinding ListProperty}' Name='target'>
  449. <ItemsControl.ItemTemplate>
  450. <DataTemplate>
  451. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  452. </DataTemplate>
  453. </ItemsControl.ItemTemplate>
  454. </ItemsControl>
  455. </Window>";
  456. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  457. var target = window.FindControl<ItemsControl>("target");
  458. var dataContext = new TestDataContext();
  459. dataContext.ListProperty.Add("Test");
  460. window.DataContext = dataContext;
  461. window.ApplyTemplate();
  462. target.ApplyTemplate();
  463. target.Presenter.ApplyTemplate();
  464. Assert.Equal(dataContext.ListProperty[0], (string)((ContentPresenter)target.Presenter.Panel.Children[0]).Content);
  465. }
  466. }
  467. [Fact]
  468. public void ThrowsOnUninferrableDataTemplateInItemsControlWithoutItemsBinding()
  469. {
  470. using (UnitTestApplication.Start(TestServices.StyledWindow))
  471. {
  472. var xaml = @"
  473. <Window xmlns='https://github.com/avaloniaui'
  474. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  475. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  476. x:DataType='local:TestDataContext'>
  477. <ItemsControl Name='target'>
  478. <ItemsControl.DataTemplates>
  479. <DataTemplate>
  480. <TextBlock Text='{CompiledBinding Property}' Name='textBlock' />
  481. </DataTemplate>
  482. </ItemsControl.DataTemplates>
  483. </ItemsControl>
  484. </Window>";
  485. ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  486. }
  487. }
  488. [Fact]
  489. public void IgnoresDataTemplateTypeFromDataTypePropertyIfXDataTypeDefined()
  490. {
  491. using (UnitTestApplication.Start(TestServices.StyledWindow))
  492. {
  493. var xaml = @"
  494. <Window xmlns='https://github.com/avaloniaui'
  495. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  496. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  497. <Window.DataTemplates>
  498. <DataTemplate DataType='local:TestDataContextBaseClass' x:DataType='local:TestDataContext'>
  499. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  500. </DataTemplate>
  501. </Window.DataTemplates>
  502. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  503. </Window>";
  504. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  505. var target = window.FindControl<ContentControl>("target");
  506. var dataContext = new TestDataContext();
  507. dataContext.StringProperty = "Initial Value";
  508. window.DataContext = dataContext;
  509. window.ApplyTemplate();
  510. target.ApplyTemplate();
  511. ((ContentPresenter)target.Presenter).UpdateChild();
  512. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
  513. }
  514. }
  515. [Fact]
  516. public void InfersCustomDataTemplateBasedOnAttribute()
  517. {
  518. using (UnitTestApplication.Start(TestServices.StyledWindow))
  519. {
  520. var xaml = @"
  521. <Window xmlns='https://github.com/avaloniaui'
  522. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  523. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  524. <Window.DataTemplates>
  525. <local:CustomDataTemplate FancyDataType='local:TestDataContext'>
  526. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  527. </local:CustomDataTemplate>
  528. </Window.DataTemplates>
  529. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  530. </Window>";
  531. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  532. var target = window.FindControl<ContentControl>("target");
  533. var dataContext = new TestDataContext();
  534. dataContext.StringProperty = "Initial Value";
  535. window.DataContext = dataContext;
  536. window.ApplyTemplate();
  537. target.ApplyTemplate();
  538. ((ContentPresenter)target.Presenter).UpdateChild();
  539. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
  540. }
  541. }
  542. [Fact]
  543. public void InfersCustomDataTemplateBasedOnAttributeFromBaseClass()
  544. {
  545. using (UnitTestApplication.Start(TestServices.StyledWindow))
  546. {
  547. var xaml = @"
  548. <Window xmlns='https://github.com/avaloniaui'
  549. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  550. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  551. <Window.DataTemplates>
  552. <local:CustomDataTemplateInherit FancyDataType='local:TestDataContext'>
  553. <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
  554. </local:CustomDataTemplateInherit>
  555. </Window.DataTemplates>
  556. <ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
  557. </Window>";
  558. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  559. var target = window.FindControl<ContentControl>("target");
  560. var dataContext = new TestDataContext();
  561. dataContext.StringProperty = "Initial Value";
  562. window.DataContext = dataContext;
  563. window.ApplyTemplate();
  564. target.ApplyTemplate();
  565. ((ContentPresenter)target.Presenter).UpdateChild();
  566. Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
  567. }
  568. }
  569. [Fact]
  570. public void ResolvesElementNameBinding()
  571. {
  572. using (UnitTestApplication.Start(TestServices.StyledWindow))
  573. {
  574. var xaml = @"
  575. <Window xmlns='https://github.com/avaloniaui'
  576. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  577. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  578. x:DataType='local:TestDataContext'>
  579. <StackPanel>
  580. <TextBlock Text='{CompiledBinding StringProperty}' x:Name='text' />
  581. <TextBlock Text='{CompiledBinding #text.Text}' x:Name='text2' />
  582. </StackPanel>
  583. </Window>";
  584. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  585. var textBlock = window.FindControl<TextBlock>("text2");
  586. var dataContext = new TestDataContext
  587. {
  588. StringProperty = "foobar"
  589. };
  590. window.DataContext = dataContext;
  591. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  592. }
  593. }
  594. [Fact]
  595. public void ResolvesElementNameBindingFromLongForm()
  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. x:DataType='local:TestDataContext'>
  604. <StackPanel>
  605. <TextBlock Text='{CompiledBinding StringProperty}' x:Name='text' />
  606. <TextBlock Text='{CompiledBinding Text, ElementName=text}' x:Name='text2' />
  607. </StackPanel>
  608. </Window>";
  609. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  610. var textBlock = window.FindControl<TextBlock>("text2");
  611. var dataContext = new TestDataContext
  612. {
  613. StringProperty = "foobar"
  614. };
  615. window.DataContext = dataContext;
  616. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  617. }
  618. }
  619. [Fact]
  620. public void ResolvesRelativeSourceBindingLongForm()
  621. {
  622. using (UnitTestApplication.Start(TestServices.StyledWindow))
  623. {
  624. var xaml = @"
  625. <Window xmlns='https://github.com/avaloniaui'
  626. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  627. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  628. x:DataType='local:TestDataContext'
  629. Title='test'>
  630. <TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType=Window}}' x:Name='text'/>
  631. </Window>";
  632. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  633. var target = window.FindControl<TextBlock>("text");
  634. window.ApplyTemplate();
  635. window.Presenter.ApplyTemplate();
  636. target.ApplyTemplate();
  637. Assert.Equal("test", target.Text);
  638. }
  639. }
  640. [Fact]
  641. public void ResolvesRelativeSourceBindingFromTemplate()
  642. {
  643. using (UnitTestApplication.Start(TestServices.StyledWindow))
  644. {
  645. var xaml = @"
  646. <ContentControl xmlns='https://github.com/avaloniaui'
  647. Focusable='True'>
  648. <ContentControl.Styles>
  649. <Style Selector='ContentControl'>
  650. <Setter Property='Template'>
  651. <ControlTemplate>
  652. <ContentPresenter Focusable='{CompiledBinding !Focusable, RelativeSource={RelativeSource TemplatedParent}}' />
  653. </ControlTemplate>
  654. </Setter>
  655. </Style>
  656. </ContentControl.Styles>
  657. </ContentControl>";
  658. var contentControl = AvaloniaRuntimeXamlLoader.Parse<ContentControl>(xaml);
  659. contentControl.DataContext = new TestDataContext(); // should be ignored
  660. contentControl.Measure(new Size(10, 10));
  661. var result = contentControl.GetTemplateChildren().OfType<ContentPresenter>().First();
  662. Assert.Equal(false, result.Focusable);
  663. }
  664. }
  665. [Fact]
  666. public void ResolvesRelativeSourceBindingFromStyleSelector()
  667. {
  668. using (UnitTestApplication.Start(TestServices.StyledWindow))
  669. {
  670. var xaml = @"
  671. <TextBox xmlns='https://github.com/avaloniaui'
  672. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  673. InnerLeftContent='Hello'>
  674. <TextBox.Styles>
  675. <Style Selector='TextBox'>
  676. <Setter Property='Template'>
  677. <ControlTemplate>
  678. <StackPanel>
  679. <ContentPresenter x:Name='Content' />
  680. <TextPresenter x:Name='PART_TextPresenter' />
  681. </StackPanel>
  682. </ControlTemplate>
  683. </Setter>
  684. <Style Selector='^ /template/ ContentPresenter#Content'>
  685. <Setter Property='Content' Value='{CompiledBinding InnerLeftContent, RelativeSource={RelativeSource TemplatedParent}}' />
  686. </Style>
  687. </Style>
  688. </TextBox.Styles>
  689. </TextBox>";
  690. var textBox = AvaloniaRuntimeXamlLoader.Parse<TextBox>(xaml);
  691. textBox.DataContext = new TestDataContext(); // should be ignored
  692. textBox.Measure(new Size(10, 10));
  693. var result = textBox.GetTemplateChildren().OfType<ContentPresenter>().First();
  694. Assert.Equal(textBox.InnerLeftContent, result.Content);
  695. }
  696. }
  697. [Fact]
  698. public void ResolvesElementNameInTemplate()
  699. {
  700. using (UnitTestApplication.Start(TestServices.StyledWindow))
  701. {
  702. var xaml = @"
  703. <ContentControl xmlns='https://github.com/avaloniaui'
  704. Content='Hello'>
  705. <ContentControl.Styles>
  706. <Style Selector='ContentControl'>
  707. <Setter Property='Template'>
  708. <ControlTemplate>
  709. <Panel>
  710. <TextBox Name='InnerTextBox' Text='Hello' />
  711. <ContentPresenter Content='{CompiledBinding Text, ElementName=InnerTextBox}' />
  712. </Panel>
  713. </ControlTemplate>
  714. </Setter>
  715. </Style>
  716. </ContentControl.Styles>
  717. </ContentControl>";
  718. var contentControl = AvaloniaRuntimeXamlLoader.Parse<ContentControl>(xaml);
  719. contentControl.Measure(new Size(10, 10));
  720. var result = contentControl.GetTemplateChildren().OfType<ContentPresenter>().First();
  721. Assert.Equal("Hello", result.Content);
  722. }
  723. }
  724. [Fact]
  725. public void Binds_To_Source()
  726. {
  727. using (UnitTestApplication.Start(TestServices.StyledWindow))
  728. {
  729. var xaml = @"
  730. <Window xmlns='https://github.com/avaloniaui'
  731. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  732. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  733. x:DataType='local:TestDataContext'
  734. Title='test'>
  735. <TextBlock Text='{CompiledBinding Length, Source=Test}' x:Name='text'/>
  736. </Window>";
  737. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  738. var target = window.FindControl<TextBlock>("text");
  739. window.ApplyTemplate();
  740. window.Presenter.ApplyTemplate();
  741. target.ApplyTemplate();
  742. Assert.Equal("Test".Length.ToString(), target.Text);
  743. }
  744. }
  745. [Fact]
  746. public void Binds_To_Source_StaticResource()
  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='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  754. x:CompileBindings='True'>
  755. <Window.Resources>
  756. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  757. </Window.Resources>
  758. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  759. </Window>";
  760. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  761. var textBlock = window.FindControl<TextBlock>("textBlock");
  762. Assert.Equal("foobar", textBlock.Text);
  763. }
  764. }
  765. [Fact]
  766. public void Binds_To_Source_StaticResource1()
  767. {
  768. using (UnitTestApplication.Start(TestServices.StyledWindow))
  769. {
  770. var xaml = @"
  771. <Window xmlns='https://github.com/avaloniaui'
  772. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  773. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  774. x:CompileBindings='True'>
  775. <Window.Resources>
  776. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  777. <x:String x:Key='otherObjectKey'>test</x:String>
  778. </Window.Resources>
  779. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  780. </Window>";
  781. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  782. var textBlock = window.FindControl<TextBlock>("textBlock");
  783. Assert.Equal("foobar", textBlock.Text);
  784. }
  785. }
  786. [Fact]
  787. public void Binds_To_Source_StaticResource_In_ResourceDictionary()
  788. {
  789. using (UnitTestApplication.Start(TestServices.StyledWindow))
  790. {
  791. var xaml = @"
  792. <Window xmlns='https://github.com/avaloniaui'
  793. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  794. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  795. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  796. <Window.Resources>
  797. <ResourceDictionary>
  798. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  799. </ResourceDictionary>
  800. </Window.Resources>
  801. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  802. </Window>";
  803. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  804. var textBlock = window.FindControl<TextBlock>("textBlock");
  805. Assert.Equal("foobar", textBlock.Text);
  806. }
  807. }
  808. [Fact]
  809. public void Binds_To_Source_StaticResource_In_ResourceDictionary1()
  810. {
  811. using (UnitTestApplication.Start(TestServices.StyledWindow))
  812. {
  813. var xaml = @"
  814. <Window xmlns='https://github.com/avaloniaui'
  815. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  816. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  817. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  818. <Window.Resources>
  819. <ResourceDictionary>
  820. <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
  821. <x:String x:Key='otherObjectKey'>test</x:String>
  822. </ResourceDictionary>
  823. </Window.Resources>
  824. <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
  825. </Window>";
  826. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  827. var textBlock = window.FindControl<TextBlock>("textBlock");
  828. Assert.Equal("foobar", textBlock.Text);
  829. }
  830. }
  831. [Fact]
  832. public void Binds_To_Source_xStatic()
  833. {
  834. using (UnitTestApplication.Start(TestServices.StyledWindow))
  835. {
  836. var xaml = @"
  837. <Window xmlns='https://github.com/avaloniaui'
  838. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  839. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  840. x:CompileBindings='True'>
  841. <ContentControl Name='contentControl' Content='{Binding Color, Source={x:Static Brushes.Red}}'/>
  842. </Window>";
  843. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  844. var contentControl = window.FindControl<ContentControl>("contentControl");
  845. Assert.Equal(Brushes.Red.Color, contentControl.Content);
  846. }
  847. }
  848. [Fact]
  849. public void CompilesBindingWhenRequested()
  850. {
  851. using (UnitTestApplication.Start(TestServices.StyledWindow))
  852. {
  853. var xaml = @"
  854. <Window xmlns='https://github.com/avaloniaui'
  855. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  856. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  857. x:DataType='local:TestDataContext'
  858. x:CompileBindings='true'>
  859. <TextBlock Text='{Binding StringProperty}' Name='textBlock' />
  860. </Window>";
  861. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  862. var textBlock = window.FindControl<TextBlock>("textBlock");
  863. var dataContext = new TestDataContext
  864. {
  865. StringProperty = "foobar"
  866. };
  867. window.DataContext = dataContext;
  868. Assert.Equal(dataContext.StringProperty, textBlock.Text);
  869. }
  870. }
  871. [Fact]
  872. public void ThrowsOnInvalidBindingPathOnCompiledBindingEnabledViaDirective()
  873. {
  874. using (UnitTestApplication.Start(TestServices.StyledWindow))
  875. {
  876. var xaml = @"
  877. <Window xmlns='https://github.com/avaloniaui'
  878. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  879. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  880. x:DataType='local:TestDataContext'
  881. x:CompileBindings='true'>
  882. <TextBlock Text='{Binding InvalidPath}' Name='textBlock' />
  883. </Window>";
  884. ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  885. }
  886. }
  887. [Fact]
  888. public void SupportParentInPath()
  889. {
  890. using (UnitTestApplication.Start(TestServices.StyledWindow))
  891. {
  892. var xaml = @"
  893. <Window xmlns='https://github.com/avaloniaui'
  894. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  895. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  896. Title='foo'>
  897. <ContentControl Content='{CompiledBinding $parent.Title}' Name='contentControl' />
  898. </Window>";
  899. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  900. var contentControl = window.FindControl<ContentControl>("contentControl");
  901. Assert.Equal("foo", contentControl.Content);
  902. }
  903. }
  904. [Fact]
  905. public void SupportConverterWithParameter()
  906. {
  907. using (UnitTestApplication.Start(TestServices.StyledWindow))
  908. {
  909. var xaml = @"
  910. <Window xmlns='https://github.com/avaloniaui'
  911. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  912. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  913. x:DataType='local:TestDataContext' x:CompileBindings='True'>
  914. <TextBlock Name='textBlock' Text='{Binding StringProperty, Converter={x:Static local:AppendConverter.Instance}, ConverterParameter=Bar}'/>
  915. </Window>";
  916. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  917. var textBlock = window.FindControl<TextBlock>("textBlock");
  918. window.DataContext = new TestDataContext() { StringProperty = "Foo" };
  919. Assert.Equal("Foo+Bar", textBlock.Text);
  920. }
  921. }
  922. [Fact]
  923. public void ThrowsOnInvalidCompileBindingsDirective()
  924. {
  925. using (UnitTestApplication.Start(TestServices.StyledWindow))
  926. {
  927. var xaml = @"
  928. <Window xmlns='https://github.com/avaloniaui'
  929. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  930. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  931. x:DataType='local:TestDataContext'
  932. x:CompileBindings='notabool'>
  933. </Window>";
  934. ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
  935. }
  936. }
  937. [Fact]
  938. public void SupportCastToTypeInExpression()
  939. {
  940. using (UnitTestApplication.Start(TestServices.StyledWindow))
  941. {
  942. var xaml = @"
  943. <Window xmlns='https://github.com/avaloniaui'
  944. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  945. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  946. x:DataType='local:TestDataContext'>
  947. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
  948. </Window>";
  949. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  950. var contentControl = window.FindControl<ContentControl>("contentControl");
  951. var dataContext = new TestDataContext();
  952. window.DataContext = dataContext;
  953. Assert.Equal(dataContext, contentControl.Content);
  954. }
  955. }
  956. [Fact]
  957. public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
  958. {
  959. using (UnitTestApplication.Start(TestServices.StyledWindow))
  960. {
  961. var xaml = @"
  962. <Window xmlns='https://github.com/avaloniaui'
  963. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  964. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  965. x:DataType='local:TestDataContext'>
  966. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
  967. </Window>";
  968. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  969. var contentControl = window.FindControl<ContentControl>("contentControl");
  970. var dataContext = "foo";
  971. window.DataContext = dataContext;
  972. Assert.Equal(null, contentControl.Content);
  973. }
  974. }
  975. [Fact]
  976. public void SupportCastToTypeInExpressionWithProperty()
  977. {
  978. using (UnitTestApplication.Start(TestServices.StyledWindow))
  979. {
  980. var xaml = @"
  981. <Window xmlns='https://github.com/avaloniaui'
  982. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  983. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  984. x:DataType='local:TestDataContext'>
  985. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
  986. </Window>";
  987. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  988. var contentControl = window.FindControl<ContentControl>("contentControl");
  989. var dataContext = new TestDataContext
  990. {
  991. StringProperty = "foobar"
  992. };
  993. window.DataContext = dataContext;
  994. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  995. }
  996. }
  997. [Fact]
  998. public void SupportCastToTypeInExpressionWithProperty1()
  999. {
  1000. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1001. {
  1002. var xaml = @"
  1003. <Window xmlns='https://github.com/avaloniaui'
  1004. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1005. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1006. x:DataType='local:TestDataContext'>
  1007. <ContentControl Content='{CompiledBinding $parent.DataContext(local:TestDataContext).StringProperty}' Name='contentControl' />
  1008. </Window>";
  1009. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1010. var contentControl = window.FindControl<ContentControl>("contentControl");
  1011. var dataContext = new TestDataContext
  1012. {
  1013. StringProperty = "foobar"
  1014. };
  1015. window.DataContext = dataContext;
  1016. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  1017. }
  1018. }
  1019. [Fact]
  1020. public void SupportCastToTypeInExpressionWithPropertyIndexer()
  1021. {
  1022. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1023. {
  1024. var xaml = @"
  1025. <Window xmlns='https://github.com/avaloniaui'
  1026. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1027. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1028. x:DataType='local:TestDataContext'>
  1029. <ContentControl Content='{CompiledBinding ((local:TestData)ObjectsArrayProperty[0]).StringProperty}' Name='contentControl' />
  1030. </Window>";
  1031. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1032. var contentControl = window.FindControl<ContentControl>("contentControl");
  1033. var data = new TestData()
  1034. {
  1035. StringProperty = "Foo"
  1036. };
  1037. var dataContext = new TestDataContext
  1038. {
  1039. ObjectsArrayProperty = new object[] { data }
  1040. };
  1041. window.DataContext = dataContext;
  1042. Assert.Equal(data.StringProperty, contentControl.Content);
  1043. }
  1044. }
  1045. [Fact]
  1046. public void SupportCastToTypeInExpressionWithProperty_DifferentTypeEvaluatesToNull()
  1047. {
  1048. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1049. {
  1050. var xaml = @"
  1051. <Window xmlns='https://github.com/avaloniaui'
  1052. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1053. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
  1054. x:DataType='local:TestDataContext'>
  1055. <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
  1056. </Window>";
  1057. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1058. var contentControl = window.FindControl<ContentControl>("contentControl");
  1059. var dataContext = new TestDataContext
  1060. {
  1061. StringProperty = "foobar"
  1062. };
  1063. window.DataContext = dataContext;
  1064. Assert.Equal(dataContext.StringProperty, contentControl.Content);
  1065. window.DataContext = "foo";
  1066. Assert.Equal(null, contentControl.Content);
  1067. }
  1068. }
  1069. [Fact]
  1070. public void SupportsEmptyPath()
  1071. {
  1072. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1073. {
  1074. var xaml = @"
  1075. <Window xmlns='https://github.com/avaloniaui'
  1076. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1077. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1078. x:DataType='local:TestDataContext'>
  1079. <TextBlock Text='{CompiledBinding}' Name='textBlock' />
  1080. </Window>";
  1081. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1082. var textBlock = window.FindControl<TextBlock>("textBlock");
  1083. var dataContext = new TestDataContext
  1084. {
  1085. StringProperty = "foobar"
  1086. };
  1087. window.DataContext = dataContext;
  1088. Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
  1089. }
  1090. }
  1091. [Fact]
  1092. public void SupportsEmptyPathWithStringFormat()
  1093. {
  1094. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1095. {
  1096. var xaml = @"
  1097. <Window xmlns='https://github.com/avaloniaui'
  1098. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1099. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1100. x:DataType='local:TestDataContext'>
  1101. <TextBlock Text='{CompiledBinding StringFormat=bar-\{0\}}' Name='textBlock' />
  1102. </Window>";
  1103. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1104. var textBlock = window.FindControl<TextBlock>("textBlock");
  1105. var dataContext = new TestDataContext
  1106. {
  1107. StringProperty = "foobar"
  1108. };
  1109. window.DataContext = dataContext;
  1110. Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
  1111. }
  1112. }
  1113. [Fact]
  1114. public void SupportsDotPath()
  1115. {
  1116. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1117. {
  1118. var xaml = @"
  1119. <Window xmlns='https://github.com/avaloniaui'
  1120. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1121. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1122. x:DataType='local:TestDataContext'>
  1123. <TextBlock Text='{CompiledBinding .}' Name='textBlock' />
  1124. </Window>";
  1125. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1126. var textBlock = window.FindControl<TextBlock>("textBlock");
  1127. var dataContext = new TestDataContext
  1128. {
  1129. StringProperty = "foobar"
  1130. };
  1131. window.DataContext = dataContext;
  1132. Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
  1133. }
  1134. }
  1135. [Fact]
  1136. public void SupportsExplicitDotPathWithStringFormat()
  1137. {
  1138. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1139. {
  1140. var xaml = @"
  1141. <Window xmlns='https://github.com/avaloniaui'
  1142. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1143. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1144. x:DataType='local:TestDataContext'>
  1145. <TextBlock Text='{CompiledBinding Path=., StringFormat=bar-\{0\}}' Name='textBlock' />
  1146. </Window>";
  1147. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1148. var textBlock = window.FindControl<TextBlock>("textBlock");
  1149. var dataContext = new TestDataContext
  1150. {
  1151. StringProperty = "foobar"
  1152. };
  1153. window.DataContext = dataContext;
  1154. Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
  1155. }
  1156. }
  1157. [Fact]
  1158. public void SupportCastToTypeInExpressionWithProperty_ExplicitPropertyCast()
  1159. {
  1160. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1161. {
  1162. var xaml = @"
  1163. <Window xmlns='https://github.com/avaloniaui'
  1164. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1165. xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'>
  1166. <ContentControl Content='{CompiledBinding $parent.((local:IHasExplicitProperty)DataContext).ExplicitProperty}' Name='contentControl' />
  1167. </Window>";
  1168. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1169. var contentControl = window.GetControl<ContentControl>("contentControl");
  1170. var dataContext = new TestDataContext();
  1171. window.DataContext = dataContext;
  1172. Assert.Equal(((IHasExplicitProperty)dataContext).ExplicitProperty, contentControl.Content);
  1173. }
  1174. }
  1175. [Fact]
  1176. public void Binds_To_Self_Without_DataType()
  1177. {
  1178. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1179. {
  1180. var xaml = @"
  1181. <Window xmlns='https://github.com/avaloniaui'
  1182. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1183. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  1184. <TextBlock Name='textBlock' Text='{CompiledBinding $self.Name}' />
  1185. </Window>";
  1186. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1187. var textBlock = window.FindControl<TextBlock>("textBlock");
  1188. window.ApplyTemplate();
  1189. window.Presenter.ApplyTemplate();
  1190. Assert.Equal(textBlock.Name, textBlock.Text);
  1191. }
  1192. }
  1193. [Fact]
  1194. public void Binds_To_Self_In_Style()
  1195. {
  1196. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1197. {
  1198. var xaml = @"
  1199. <Window xmlns='https://github.com/avaloniaui'
  1200. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  1201. <Window.Styles>
  1202. <Style Selector='Button'>
  1203. <Setter Property='IsVisible' Value='{CompiledBinding $self.IsEnabled}' />
  1204. </Style>
  1205. </Window.Styles>
  1206. <Button Name='button' />
  1207. </Window>";
  1208. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1209. var button = window.FindControl<Button>("button");
  1210. window.ApplyTemplate();
  1211. window.Presenter.ApplyTemplate();
  1212. Assert.True(button.IsVisible);
  1213. button.IsEnabled = false;
  1214. Assert.False(button.IsVisible);
  1215. }
  1216. }
  1217. [Fact]
  1218. public void SupportsMethodBindingAsDelegate()
  1219. {
  1220. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1221. {
  1222. var xaml = @"
  1223. <Window xmlns='https://github.com/avaloniaui'
  1224. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1225. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1226. x:DataType='local:MethodDataContext'>
  1227. <StackPanel>
  1228. <ContentControl Content='{CompiledBinding Action}' Name='action' />
  1229. <ContentControl Content='{CompiledBinding Func}' Name='func' />
  1230. <ContentControl Content='{CompiledBinding Action16}' Name='action16' />
  1231. <ContentControl Content='{CompiledBinding Func16}' Name='func16' />
  1232. <ContentControl Content='{CompiledBinding CustomDelegateTypeVoid}' Name='customvoid' />
  1233. <ContentControl Content='{CompiledBinding CustomDelegateTypeInt}' Name='customint' />
  1234. </StackPanel>
  1235. </Window>";
  1236. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1237. window.DataContext = new MethodDataContext();
  1238. Assert.IsAssignableFrom(typeof(Action), window.FindControl<ContentControl>("action").Content);
  1239. Assert.IsAssignableFrom(typeof(Func<int>), window.FindControl<ContentControl>("func").Content);
  1240. Assert.IsAssignableFrom(typeof(Action<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.FindControl<ContentControl>("action16").Content);
  1241. Assert.IsAssignableFrom(typeof(Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.FindControl<ContentControl>("func16").Content);
  1242. Assert.True(typeof(Delegate).IsAssignableFrom(window.FindControl<ContentControl>("customvoid").Content.GetType()));
  1243. Assert.True(typeof(Delegate).IsAssignableFrom(window.FindControl<ContentControl>("customint").Content.GetType()));
  1244. }
  1245. }
  1246. [Fact]
  1247. public void Binding_Method_To_Command_Works()
  1248. {
  1249. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1250. {
  1251. var xaml = @"
  1252. <Window xmlns='https://github.com/avaloniaui'
  1253. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1254. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1255. x:DataType='local:MethodAsCommandDataContext'>
  1256. <Button Name='button' Command='{CompiledBinding Method}'/>
  1257. </Window>";
  1258. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1259. var button = window.FindControl<Button>("button");
  1260. var vm = new MethodAsCommandDataContext();
  1261. button.DataContext = vm;
  1262. window.ApplyTemplate();
  1263. Assert.NotNull(button.Command);
  1264. PerformClick(button);
  1265. Assert.Equal("Called", vm.Value);
  1266. }
  1267. }
  1268. [Fact]
  1269. public void Binding_Method_With_Parameter_To_Command_Works()
  1270. {
  1271. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1272. {
  1273. var xaml = @"
  1274. <Window xmlns='https://github.com/avaloniaui'
  1275. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1276. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1277. x:DataType='local:MethodAsCommandDataContext'>
  1278. <Button Name='button' Command='{CompiledBinding Method1}' CommandParameter='5'/>
  1279. </Window>";
  1280. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1281. var button = window.FindControl<Button>("button");
  1282. var vm = new MethodAsCommandDataContext();
  1283. button.DataContext = vm;
  1284. window.ApplyTemplate();
  1285. Assert.NotNull(button.Command);
  1286. PerformClick(button);
  1287. Assert.Equal("Called 5", vm.Value);
  1288. }
  1289. }
  1290. [Fact]
  1291. public void Binding_Method_To_TextBlock_Text_Works()
  1292. {
  1293. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1294. {
  1295. var xaml = @"
  1296. <Window xmlns='https://github.com/avaloniaui'
  1297. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1298. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1299. x:DataType='local:MethodAsCommandDataContext'>
  1300. <TextBlock Name='textBlock' Text='{CompiledBinding Method}'/>
  1301. </Window>";
  1302. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1303. var textBlock = window.FindControl<TextBlock>("textBlock");
  1304. var vm = new MethodAsCommandDataContext();
  1305. textBlock.DataContext = vm;
  1306. window.ApplyTemplate();
  1307. Assert.NotNull(textBlock.Text);
  1308. }
  1309. }
  1310. [Theory]
  1311. [InlineData(null, "Not called")]
  1312. [InlineData("A", "Do A")]
  1313. public void Binding_Method_With_Parameter_To_Command_CanExecute(object commandParameter, string result)
  1314. {
  1315. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1316. {
  1317. var xaml = @"
  1318. <Window xmlns='https://github.com/avaloniaui'
  1319. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1320. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1321. x:DataType='local:MethodAsCommandDataContext'>
  1322. <Button Name='button' Command='{CompiledBinding Do}' CommandParameter='{CompiledBinding Parameter, Mode=OneTime}'/>
  1323. </Window>";
  1324. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1325. var button = window.FindControl<Button>("button");
  1326. var vm = new MethodAsCommandDataContext()
  1327. {
  1328. Parameter = commandParameter
  1329. };
  1330. button.DataContext = vm;
  1331. window.ApplyTemplate();
  1332. Assert.NotNull(button.Command);
  1333. PerformClick(button);
  1334. Assert.Equal(vm.Value, result);
  1335. }
  1336. }
  1337. [Fact]
  1338. public void Binding_Method_With_Parameter_To_Command_CanExecute_DependsOn()
  1339. {
  1340. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1341. {
  1342. var xaml = @"
  1343. <Window xmlns='https://github.com/avaloniaui'
  1344. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1345. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1346. x:DataType='local:MethodAsCommandDataContext'>
  1347. <Button Name='button' Command='{CompiledBinding Do}' CommandParameter='{CompiledBinding Parameter, Mode=OneWay}'/>
  1348. </Window>";
  1349. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  1350. var button = window.FindControl<Button>("button");
  1351. var vm = new MethodAsCommandDataContext()
  1352. {
  1353. Parameter = null,
  1354. };
  1355. button.DataContext = vm;
  1356. window.ApplyTemplate();
  1357. Assert.NotNull(button.Command);
  1358. Assert.Equal(button.IsEffectivelyEnabled, false);
  1359. vm.Parameter = true;
  1360. Threading.Dispatcher.UIThread.RunJobs();
  1361. Assert.Equal(button.IsEffectivelyEnabled, true);
  1362. }
  1363. }
  1364. [Fact]
  1365. public void ResolvesDataTypeForAssignBinding()
  1366. {
  1367. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1368. {
  1369. var xaml = @"
  1370. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1371. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1372. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1373. x:DataType='local:TestDataContext'
  1374. X='{CompiledBinding StringProperty}' />";
  1375. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
  1376. var compiledPath = ((CompiledBindingExtension)control.X).Path;
  1377. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1378. Assert.Equal(typeof(string), node.Property.PropertyType);
  1379. }
  1380. }
  1381. [Fact]
  1382. public void ResolvesDataTypeForAssignBinding_FromBindingProperty()
  1383. {
  1384. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1385. {
  1386. var xaml = @"
  1387. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1388. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1389. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1390. X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
  1391. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
  1392. var compiledPath = ((CompiledBindingExtension)control.X).Path;
  1393. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1394. Assert.Equal(typeof(string), node.Property.PropertyType);
  1395. }
  1396. }
  1397. [Fact]
  1398. public void Uses_RuntimeLoader_Configuration_To_Enabled_Compiled()
  1399. {
  1400. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1401. {
  1402. var xaml = @"
  1403. <local:AssignBindingControl xmlns='https://github.com/avaloniaui'
  1404. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  1405. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
  1406. X='{Binding StringProperty, DataType=local:TestDataContext}' />";
  1407. var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml),
  1408. new RuntimeXamlLoaderConfiguration { UseCompiledBindingsByDefault = true });
  1409. var compiledPath = ((CompiledBindingExtension)control.X).Path;
  1410. var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
  1411. Assert.Equal(typeof(string), node.Property.PropertyType);
  1412. }
  1413. }
  1414. void Throws(string type, Action cb)
  1415. {
  1416. try
  1417. {
  1418. cb();
  1419. }
  1420. catch (Exception e) when (e.GetType().Name == type)
  1421. {
  1422. return;
  1423. }
  1424. throw new Exception("Expected " + type);
  1425. }
  1426. void ThrowsXamlParseException(Action cb) => Throws("XamlParseException", cb);
  1427. void ThrowsXamlTransformException(Action cb) => Throws("XamlTransformException", cb);
  1428. static void PerformClick(Button button)
  1429. {
  1430. button.RaiseEvent(new KeyEventArgs
  1431. {
  1432. RoutedEvent = InputElement.KeyDownEvent,
  1433. Key = Input.Key.Enter,
  1434. });
  1435. }
  1436. }
  1437. public interface INonIntegerIndexer
  1438. {
  1439. string this[string key] { get; set; }
  1440. }
  1441. public interface INonIntegerIndexerDerived : INonIntegerIndexer
  1442. { }
  1443. public interface IHasProperty
  1444. {
  1445. string StringProperty { get; set; }
  1446. }
  1447. public interface IHasPropertyDerived : IHasProperty
  1448. { }
  1449. public interface IHasExplicitProperty
  1450. {
  1451. string ExplicitProperty { get; }
  1452. }
  1453. public class AppendConverter : IValueConverter
  1454. {
  1455. public static IValueConverter Instance { get; } = new AppendConverter();
  1456. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  1457. => string.Format("{0}+{1}", value, parameter);
  1458. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  1459. => throw new NotImplementedException();
  1460. }
  1461. public class TestData
  1462. {
  1463. public string StringProperty { get; set; }
  1464. }
  1465. public class TestDataContextBaseClass {}
  1466. public class TestDataContext : TestDataContextBaseClass, IHasPropertyDerived, IHasExplicitProperty
  1467. {
  1468. public string StringProperty { get; set; }
  1469. public Task<string> TaskProperty { get; set; }
  1470. public IObservable<string> ObservableProperty { get; set; }
  1471. public ObservableCollection<string> ObservableCollectionProperty { get; set; } = new ObservableCollection<string>();
  1472. public string[] ArrayProperty { get; set; }
  1473. public object[] ObjectsArrayProperty { get; set; }
  1474. public List<string> ListProperty { get; set; } = new List<string>();
  1475. public NonIntegerIndexer NonIntegerIndexerProperty { get; set; } = new NonIntegerIndexer();
  1476. public INonIntegerIndexerDerived NonIntegerIndexerInterfaceProperty => NonIntegerIndexerProperty;
  1477. string IHasExplicitProperty.ExplicitProperty => "Hello";
  1478. public string ExplicitProperty => "Bye";
  1479. public static string StaticProperty => "World";
  1480. public class NonIntegerIndexer : NotifyingBase, INonIntegerIndexerDerived
  1481. {
  1482. private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();
  1483. public string this[string key]
  1484. {
  1485. get
  1486. {
  1487. return _storage[key];
  1488. }
  1489. set
  1490. {
  1491. _storage[key] = value;
  1492. RaisePropertyChanged(CommonPropertyNames.IndexerName);
  1493. }
  1494. }
  1495. }
  1496. }
  1497. public class MethodDataContext
  1498. {
  1499. public void Action() { }
  1500. public int Func() => 1;
  1501. 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) { }
  1502. 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;
  1503. 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) { }
  1504. 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;
  1505. }
  1506. public class MethodAsCommandDataContext : INotifyPropertyChanged
  1507. {
  1508. public event PropertyChangedEventHandler PropertyChanged;
  1509. public string Method() => Value = "Called";
  1510. public string Method1(int i) => Value = $"Called {i}";
  1511. public string Method2(int i, int j) => Value = $"Called {i},{j}";
  1512. public string Value { get; private set; } = "Not called";
  1513. object _parameter;
  1514. public object Parameter
  1515. {
  1516. get
  1517. {
  1518. return _parameter;
  1519. }
  1520. set
  1521. {
  1522. if (_parameter == value)
  1523. {
  1524. return;
  1525. }
  1526. _parameter = value;
  1527. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Parameter)));
  1528. }
  1529. }
  1530. public void Do(object parameter)
  1531. {
  1532. Value = $"Do {parameter}";
  1533. }
  1534. [Metadata.DependsOn(nameof(Parameter))]
  1535. public bool CanDo(object parameter)
  1536. {
  1537. return ReferenceEquals(null, parameter) == false;
  1538. }
  1539. }
  1540. public class CustomDataTemplate : IDataTemplate
  1541. {
  1542. [DataType]
  1543. public Type FancyDataType { get; set; }
  1544. [Content]
  1545. [TemplateContent]
  1546. public object Content { get; set; }
  1547. public bool Match(object data) => FancyDataType?.IsInstanceOfType(data) ?? true;
  1548. public IControl Build(object data) => TemplateContent.Load(Content)?.Control;
  1549. }
  1550. public class CustomDataTemplateInherit : CustomDataTemplate { }
  1551. public class AssignBindingControl : Control
  1552. {
  1553. [AssignBinding] public IBinding X { get; set; }
  1554. }
  1555. }