ScrollContentPresenterTests.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reactive.Linq;
  4. using Avalonia.Controls.Presenters;
  5. using Avalonia.Controls.Templates;
  6. using Avalonia.Layout;
  7. using Avalonia.UnitTests;
  8. using Xunit;
  9. using Xunit.Sdk;
  10. namespace Avalonia.Controls.UnitTests.Presenters
  11. {
  12. public class ScrollContentPresenterTests : NameScopeTests
  13. {
  14. [Theory]
  15. [InlineData(HorizontalAlignment.Stretch, VerticalAlignment.Stretch, 10, 10, 80, 80)]
  16. [InlineData(HorizontalAlignment.Left, VerticalAlignment.Stretch, 10, 10, 16, 80)]
  17. [InlineData(HorizontalAlignment.Right, VerticalAlignment.Stretch, 74, 10, 16, 80)]
  18. [InlineData(HorizontalAlignment.Center, VerticalAlignment.Stretch, 42, 10, 16, 80)]
  19. [InlineData(HorizontalAlignment.Stretch, VerticalAlignment.Top, 10, 10, 80, 16)]
  20. [InlineData(HorizontalAlignment.Stretch, VerticalAlignment.Bottom, 10, 74, 80, 16)]
  21. [InlineData(HorizontalAlignment.Stretch, VerticalAlignment.Center, 10, 42, 80, 16)]
  22. public void Alignment_And_Padding_Are_Applied_To_Child_Bounds(
  23. HorizontalAlignment h,
  24. VerticalAlignment v,
  25. double expectedX,
  26. double expectedY,
  27. double expectedWidth,
  28. double expectedHeight)
  29. {
  30. Border content;
  31. var target = new ScrollContentPresenter
  32. {
  33. Padding = new Thickness(10),
  34. Content = content = new Border
  35. {
  36. MinWidth = 16,
  37. MinHeight = 16,
  38. HorizontalAlignment = h,
  39. VerticalAlignment = v,
  40. },
  41. };
  42. target.UpdateChild();
  43. target.Measure(new Size(100, 100));
  44. target.Arrange(new Rect(0, 0, 100, 100));
  45. Assert.Equal(new Rect(expectedX, expectedY, expectedWidth, expectedHeight), content.Bounds);
  46. }
  47. [Fact]
  48. public void DesiredSize_Is_Content_Size_When_Smaller_Than_AvailableSize()
  49. {
  50. var target = new ScrollContentPresenter
  51. {
  52. Padding = new Thickness(10),
  53. Content = new Border
  54. {
  55. MinWidth = 16,
  56. MinHeight = 16,
  57. },
  58. };
  59. target.UpdateChild();
  60. target.Measure(new Size(100, 100));
  61. target.Arrange(new Rect(0, 0, 100, 100));
  62. Assert.Equal(new Size(16, 16), target.DesiredSize);
  63. }
  64. [Fact]
  65. public void DesiredSize_Is_AvailableSize_When_Content_Larger_Than_AvailableSize()
  66. {
  67. var target = new ScrollContentPresenter
  68. {
  69. Padding = new Thickness(10),
  70. Content = new Border
  71. {
  72. MinWidth = 160,
  73. MinHeight = 160,
  74. },
  75. };
  76. target.UpdateChild();
  77. target.Measure(new Size(100, 100));
  78. target.Arrange(new Rect(0, 0, 100, 100));
  79. Assert.Equal(new Size(100, 100), target.DesiredSize);
  80. }
  81. [Fact]
  82. public void Content_Can_Be_Larger_Than_Viewport()
  83. {
  84. TestControl content;
  85. var target = new ScrollContentPresenter
  86. {
  87. CanHorizontallyScroll = true,
  88. CanVerticallyScroll = true,
  89. Content = content = new TestControl(),
  90. };
  91. target.UpdateChild();
  92. target.Measure(new Size(100, 100));
  93. target.Arrange(new Rect(0, 0, 100, 100));
  94. Assert.Equal(new Rect(0, 0, 150, 150), content.Bounds);
  95. }
  96. [Fact]
  97. public void Content_Can_Be_Offset()
  98. {
  99. Border content;
  100. var target = new ScrollContentPresenter
  101. {
  102. CanHorizontallyScroll = true,
  103. CanVerticallyScroll = true,
  104. Content = content = new Border
  105. {
  106. Width = 150,
  107. Height = 150,
  108. },
  109. };
  110. target.UpdateChild();
  111. target.Measure(new Size(100, 100));
  112. target.Arrange(new Rect(0, 0, 100, 100));
  113. target.Offset = new Vector(25, 25);
  114. target.Measure(new Size(100, 100));
  115. target.Arrange(new Rect(0, 0, 100, 100));
  116. Assert.Equal(new Rect(-25, -25, 150, 150), content.Bounds);
  117. }
  118. [Fact]
  119. public void Measure_Should_Pass_Bounded_X_If_CannotScrollHorizontally()
  120. {
  121. var child = new TestControl();
  122. var target = new ScrollContentPresenter
  123. {
  124. CanVerticallyScroll = true,
  125. Content = child,
  126. };
  127. target.UpdateChild();
  128. target.Measure(new Size(100, 100));
  129. Assert.Equal(new Size(100, double.PositiveInfinity), child.AvailableSize);
  130. }
  131. [Fact]
  132. public void Measure_Should_Pass_Unbounded_X_If_CanScrollHorizontally()
  133. {
  134. var child = new TestControl();
  135. var target = new ScrollContentPresenter
  136. {
  137. CanHorizontallyScroll = true,
  138. CanVerticallyScroll = true,
  139. Content = child,
  140. };
  141. target.UpdateChild();
  142. target.Measure(new Size(100, 100));
  143. Assert.Equal(Size.Infinity, child.AvailableSize);
  144. }
  145. [Fact]
  146. public void Arrange_Should_Set_Viewport_And_Extent_In_That_Order()
  147. {
  148. var target = new ScrollContentPresenter
  149. {
  150. Content = new Border { Width = 40, Height = 50 }
  151. };
  152. var set = new List<string>();
  153. target.UpdateChild();
  154. target.Measure(new Size(100, 100));
  155. target.GetObservable(ScrollViewer.ViewportProperty).Skip(1).Subscribe(_ => set.Add("Viewport"));
  156. target.GetObservable(ScrollViewer.ExtentProperty).Skip(1).Subscribe(_ => set.Add("Extent"));
  157. target.Arrange(new Rect(0, 0, 100, 100));
  158. Assert.Equal(new[] { "Viewport", "Extent" }, set);
  159. }
  160. [Fact]
  161. public void Should_Correctly_Arrange_Child_Larger_Than_Viewport()
  162. {
  163. var child = new Canvas { MinWidth = 150, MinHeight = 150 };
  164. var target = new ScrollContentPresenter { Content = child, };
  165. target.UpdateChild();
  166. target.Measure(Size.Infinity);
  167. target.Arrange(new Rect(0, 0, 100, 100));
  168. Assert.Equal(new Size(150, 150), child.Bounds.Size);
  169. }
  170. [Fact]
  171. public void Arrange_Should_Constrain_Child_Width_When_CanHorizontallyScroll_False()
  172. {
  173. var child = new WrapPanel
  174. {
  175. Children =
  176. {
  177. new Border { Width = 40, Height = 50 },
  178. new Border { Width = 40, Height = 50 },
  179. new Border { Width = 40, Height = 50 },
  180. }
  181. };
  182. var target = new ScrollContentPresenter
  183. {
  184. Content = child,
  185. CanHorizontallyScroll = false,
  186. };
  187. target.UpdateChild();
  188. target.Measure(Size.Infinity);
  189. target.Arrange(new Rect(0, 0, 100, 100));
  190. Assert.Equal(100, child.Bounds.Width);
  191. }
  192. [Fact]
  193. public void Extent_Should_Include_Content_Margin()
  194. {
  195. var target = new ScrollContentPresenter
  196. {
  197. Content = new Border
  198. {
  199. Width = 100,
  200. Height = 100,
  201. Margin = new Thickness(5),
  202. }
  203. };
  204. target.UpdateChild();
  205. target.Measure(new Size(50, 50));
  206. target.Arrange(new Rect(0, 0, 50, 50));
  207. Assert.Equal(new Size(110, 110), target.Extent);
  208. }
  209. [Fact]
  210. public void Extent_Should_Include_Content_Margin_Scaled_With_Layout_Rounding()
  211. {
  212. var root = new TestRoot
  213. {
  214. LayoutScaling = 1.25,
  215. UseLayoutRounding = true
  216. };
  217. var target = new ScrollContentPresenter
  218. {
  219. HorizontalAlignment = HorizontalAlignment.Center,
  220. VerticalAlignment = VerticalAlignment.Center,
  221. Content = new Border
  222. {
  223. Width = 200,
  224. Height = 200,
  225. Margin = new Thickness(2)
  226. }
  227. };
  228. root.Child = target;
  229. target.UpdateChild();
  230. target.Measure(new Size(1000, 1000));
  231. target.Arrange(new Rect(0, 0, 1000, 1000));
  232. Assert.Equal(new Size(203.2, 203.2), target.Viewport);
  233. Assert.Equal(new Size(203.2, 203.2), target.Extent);
  234. }
  235. [Fact]
  236. public void Extent_Should_Be_Rounded_To_Viewport_When_Close()
  237. {
  238. var root = new TestRoot
  239. {
  240. LayoutScaling = 1.75,
  241. UseLayoutRounding = true
  242. };
  243. var target = new ScrollContentPresenter
  244. {
  245. HorizontalAlignment = HorizontalAlignment.Center,
  246. VerticalAlignment = VerticalAlignment.Center,
  247. Content = new Border
  248. {
  249. Width = 164.57142857142858,
  250. Height = 164.57142857142858,
  251. Margin = new Thickness(6)
  252. }
  253. };
  254. root.Child = target;
  255. target.UpdateChild();
  256. target.Measure(new Size(1000, 1000));
  257. target.Arrange(new Rect(0, 0, 1000, 1000));
  258. var nonRoundedVieViewport = target.Child!.Bounds.Size.Inflate(
  259. LayoutHelper.RoundLayoutThickness(target.Child.Margin, root.LayoutScaling));
  260. Assert.Equal(new Size(176.00000000000003, 176.00000000000003), nonRoundedVieViewport);
  261. Assert.Equal(new Size(176, 176), target.Viewport);
  262. Assert.Equal(new Size(176, 176), target.Extent);
  263. }
  264. [Fact]
  265. public void Extent_Width_Should_Be_Arrange_Width_When_CanScrollHorizontally_False()
  266. {
  267. var child = new WrapPanel
  268. {
  269. Children =
  270. {
  271. new Border { Width = 40, Height = 50 },
  272. new Border { Width = 40, Height = 50 },
  273. new Border { Width = 40, Height = 50 },
  274. }
  275. };
  276. var target = new ScrollContentPresenter
  277. {
  278. Content = child,
  279. CanHorizontallyScroll = false,
  280. };
  281. target.UpdateChild();
  282. target.Measure(Size.Infinity);
  283. target.Arrange(new Rect(0, 0, 100, 100));
  284. Assert.Equal(new Size(100, 100), target.Extent);
  285. }
  286. [Fact]
  287. public void Setting_Offset_Should_Invalidate_Arrange()
  288. {
  289. var target = new ScrollContentPresenter
  290. {
  291. Content = new Border { Width = 140, Height = 150 }
  292. };
  293. target.UpdateChild();
  294. target.Measure(new Size(100, 100));
  295. target.Arrange(new Rect(0, 0, 100, 100));
  296. target.Offset = new Vector(10, 100);
  297. Assert.True(target.IsMeasureValid);
  298. Assert.False(target.IsArrangeValid);
  299. }
  300. [Fact]
  301. public void BringDescendantIntoView_Should_Update_Offset()
  302. {
  303. var target = new ScrollContentPresenter
  304. {
  305. Width = 100,
  306. Height = 100,
  307. CanVerticallyScroll = true,
  308. CanHorizontallyScroll = true,
  309. Content = new Border
  310. {
  311. Width = 200,
  312. Height = 200,
  313. }
  314. };
  315. target.UpdateChild();
  316. target.Measure(Size.Infinity);
  317. target.Arrange(new Rect(0, 0, 100, 100));
  318. target.BringDescendantIntoView(target.Child!, new Rect(200, 200, 0, 0));
  319. Assert.Equal(new Vector(100, 100), target.Offset);
  320. }
  321. [Fact]
  322. public void BringDescendantIntoView_Should_Handle_Child_Margin()
  323. {
  324. Border border;
  325. var target = new ScrollContentPresenter
  326. {
  327. CanHorizontallyScroll = true,
  328. CanVerticallyScroll = true,
  329. Width = 100,
  330. Height = 100,
  331. Content = new Decorator
  332. {
  333. Margin = new Thickness(50),
  334. Child = border = new Border
  335. {
  336. Width = 200,
  337. Height = 200,
  338. }
  339. }
  340. };
  341. target.UpdateChild();
  342. target.Measure(Size.Infinity);
  343. target.Arrange(new Rect(0, 0, 100, 100));
  344. target.BringDescendantIntoView(border, new Rect(200, 200, 0, 0));
  345. Assert.Equal(new Vector(150, 150), target.Offset);
  346. }
  347. [Fact]
  348. public void BringDescendantIntoView_Should_Move_Child_Even_With_Margin_In_Parent()
  349. {
  350. var namescope = new NameScope();
  351. var content = new StackPanel()
  352. {
  353. Orientation = Orientation.Vertical,
  354. Width = 100,
  355. Margin = new Thickness(0, 200),
  356. };
  357. for(int i = 0; i < 100; i++)
  358. {
  359. var child = new Border
  360. {
  361. Width = 100,
  362. Height = 20,
  363. Name = $"Border{i}"
  364. }.RegisterInNameScope(namescope);
  365. content.Children.Add(child);
  366. }
  367. var target = new ScrollContentPresenter
  368. {
  369. CanHorizontallyScroll = true,
  370. CanVerticallyScroll = true,
  371. Width = 200,
  372. Height = 100,
  373. Content = new Decorator
  374. {
  375. Child = content
  376. }
  377. };
  378. NameScope.SetNameScope(target, namescope);
  379. target.UpdateChild();
  380. target.Measure(Size.Infinity);
  381. target.Arrange(new Rect(0, 0, 100, 100));
  382. // Border20 is at position 0,600 with bottom at Y=620
  383. var border20 = target.FindControl<Border>("Border20");
  384. target.BringDescendantIntoView(border20, new Rect(border20.Bounds.Size));
  385. // With viewport Height of 100, border becomes fully visible when alligned from the bottom at Offset Y=520, i.e. 620-100
  386. Assert.Equal(new Vector(0, 520), target.Offset);
  387. // Reset stack panel's margin
  388. content.Margin = default;
  389. target.Measure(Size.Infinity);
  390. target.Arrange(new Rect(0, 0, 100, 100));
  391. // Border20 is at position 0,800 with bottom at Y=820
  392. var border40 = target.FindControl<Border>("Border40");
  393. target.BringDescendantIntoView(border40, new Rect(border40.Bounds.Size));
  394. // With viewport Height of 100, border becomes fully visible when alligned from the bottom at Offset Y=720, i.e. 820-100
  395. Assert.Equal(new Vector(0, 720), target.Offset);
  396. }
  397. [Fact]
  398. public void BringDescendantIntoView_Should_Not_Move_Child_If_Completely_In_View()
  399. {
  400. var namescope = new NameScope();
  401. var content = new StackPanel()
  402. {
  403. Orientation = Orientation.Vertical,
  404. Width = 100,
  405. };
  406. for(int i = 0; i < 100; i++)
  407. {
  408. var child = new Border
  409. {
  410. Width = 100,
  411. Height = 20,
  412. Name = $"Border{i}"
  413. }.RegisterInNameScope(namescope);
  414. content.Children.Add(child);
  415. }
  416. var target = new ScrollContentPresenter
  417. {
  418. CanHorizontallyScroll = true,
  419. CanVerticallyScroll = true,
  420. Width = 200,
  421. Height = 100,
  422. Content = new Decorator
  423. {
  424. Child = content
  425. }
  426. };
  427. NameScope.SetNameScope(target, namescope);
  428. target.UpdateChild();
  429. target.Measure(Size.Infinity);
  430. target.Arrange(new Rect(0, 0, 100, 100));
  431. var border3 = target.FindControl<Border>("Border3");
  432. target.BringDescendantIntoView(border3, new Rect(border3.Bounds.Size));
  433. // Border3 is still in view, offset hasn't changed
  434. Assert.Equal(new Vector(0, 0), target.Offset);
  435. }
  436. [Fact]
  437. public void BringDescendantIntoView_Should_Move_Child_At_Least_Partially_Above_Viewport()
  438. {
  439. Border border = new Border
  440. {
  441. Width = 100,
  442. Height = 20
  443. };
  444. var content = new StackPanel()
  445. {
  446. Orientation = Orientation.Vertical,
  447. Width = 100,
  448. };
  449. for(int i = 0; i < 100; i++)
  450. {
  451. // border position will be (0,60)
  452. var child = i == 3 ? border : new Border
  453. {
  454. Width = 100,
  455. Height = 20,
  456. };
  457. content.Children.Add(child);
  458. }
  459. var target = new ScrollContentPresenter
  460. {
  461. CanHorizontallyScroll = true,
  462. CanVerticallyScroll = true,
  463. Width = 200,
  464. Height = 100,
  465. Content = new Decorator
  466. {
  467. Child = content
  468. }
  469. };
  470. target.UpdateChild();
  471. target.Measure(Size.Infinity);
  472. target.Arrange(new Rect(0, 0, 100, 100));
  473. // move border to above the view port
  474. target.Offset = new Vector(0, 90);
  475. target.Arrange(new Rect(0, 0, 100, 100));
  476. target.BringDescendantIntoView(border, new Rect(border.Bounds.Size));
  477. Assert.Equal(new Vector(0, 60), target.Offset);
  478. // move border to partially above the view port
  479. target.Offset = new Vector(0, 70);
  480. target.Arrange(new Rect(0, 0, 100, 100));
  481. target.BringDescendantIntoView(border, new Rect(border.Bounds.Size));
  482. Assert.Equal(new Vector(0, 60), target.Offset);
  483. }
  484. [Fact]
  485. public void BringDescendantIntoView_Should_Not_Move_Child_If_Completely_Covers_Viewport()
  486. {
  487. Border border = new Border
  488. {
  489. Width = 100,
  490. Height = 200
  491. };
  492. var content = new StackPanel()
  493. {
  494. Orientation = Orientation.Vertical,
  495. Width = 100,
  496. };
  497. for (int i = 0; i < 100; i++)
  498. {
  499. // border position will be (0,60)
  500. var child = i == 3 ? border : new Border
  501. {
  502. Width = 100,
  503. Height = 20,
  504. };
  505. content.Children.Add(child);
  506. }
  507. var target = new ScrollContentPresenter
  508. {
  509. CanHorizontallyScroll = true,
  510. CanVerticallyScroll = true,
  511. Width = 200,
  512. Height = 100,
  513. Content = new Decorator
  514. {
  515. Child = content
  516. }
  517. };
  518. target.UpdateChild();
  519. target.Measure(Size.Infinity);
  520. target.Arrange(new Rect(0, 0, 100, 100));
  521. // move border such that it's partially above viewport and partially below viewport
  522. target.Offset = new Vector(0, 90);
  523. target.Arrange(new Rect(0, 0, 100, 100));
  524. target.BringDescendantIntoView(border, new Rect(border.Bounds.Size));
  525. Assert.Equal(new Vector(0, 90), target.Offset);
  526. }
  527. [Fact]
  528. public void BringDescendantIntoView_Should_Move_Child_At_Least_Partially_Below_Viewport()
  529. {
  530. Border border = new Border
  531. {
  532. Width = 100,
  533. Height = 20
  534. };
  535. var content = new StackPanel()
  536. {
  537. Orientation = Orientation.Vertical,
  538. Width = 100,
  539. };
  540. for (int i = 0; i < 100; i++)
  541. {
  542. // border position will be (0,180)
  543. var child = i == 9 ? border : new Border
  544. {
  545. Width = 100,
  546. Height = 20,
  547. };
  548. content.Children.Add(child);
  549. }
  550. var target = new ScrollContentPresenter
  551. {
  552. CanHorizontallyScroll = true,
  553. CanVerticallyScroll = true,
  554. Width = 200,
  555. Height = 100,
  556. Content = new Decorator
  557. {
  558. Child = content
  559. }
  560. };
  561. target.UpdateChild();
  562. target.Measure(Size.Infinity);
  563. target.Arrange(new Rect(0, 0, 100, 100));
  564. // border is at (0, 180) and below the viewport
  565. target.BringDescendantIntoView(border, new Rect(border.Bounds.Size));
  566. Assert.Equal(new Vector(0, 100), target.Offset);
  567. // move border to partially below the view port
  568. target.Offset = new Vector(0, 90);
  569. target.BringDescendantIntoView(border, new Rect(border.Bounds.Size));
  570. }
  571. [Fact]
  572. public void Nested_Presenters_Should_Scroll_Outer_When_Content_Exceeds_Viewport()
  573. {
  574. ScrollContentPresenter innerPresenter;
  575. Border border;
  576. var outerPresenter = new ScrollContentPresenter
  577. {
  578. CanHorizontallyScroll = true,
  579. CanVerticallyScroll = true,
  580. Width = 100,
  581. Height = 100,
  582. Content = innerPresenter = new ScrollContentPresenter
  583. {
  584. CanHorizontallyScroll = true,
  585. CanVerticallyScroll = true,
  586. Width = 100,
  587. Height = 200,
  588. Content = border = new Border
  589. {
  590. Width = 200, // larger than viewport
  591. Height = 25,
  592. HorizontalAlignment = HorizontalAlignment.Left,
  593. VerticalAlignment = VerticalAlignment.Top,
  594. Margin = new Thickness(0, 120, 0, 0)
  595. }
  596. }
  597. };
  598. innerPresenter.UpdateChild();
  599. outerPresenter.UpdateChild();
  600. outerPresenter.Measure(new Size(100, 100));
  601. outerPresenter.Arrange(new Rect(0, 0, 100, 100));
  602. border.BringIntoView();
  603. Assert.Equal(new Vector(0, 45), outerPresenter.Offset);
  604. Assert.Equal(new Vector(0, 0), innerPresenter.Offset);
  605. }
  606. [Fact]
  607. public void Nested_Presenters_Should_Scroll_Outer_When_Viewports_Are_Close()
  608. {
  609. ScrollContentPresenter innerPresenter;
  610. Border border;
  611. var outerPresenter = new ScrollContentPresenter
  612. {
  613. CanHorizontallyScroll = true,
  614. CanVerticallyScroll = true,
  615. Width = 100,
  616. Height = 170.0568181818182,
  617. UseLayoutRounding = false,
  618. Content = innerPresenter = new ScrollContentPresenter
  619. {
  620. CanHorizontallyScroll = true,
  621. CanVerticallyScroll = true,
  622. Width = 100,
  623. Height = 493.2613636363636,
  624. UseLayoutRounding = false,
  625. Content = new StackPanel
  626. {
  627. Children =
  628. {
  629. new Border
  630. {
  631. Height = 455.31818181818187,
  632. UseLayoutRounding = false
  633. },
  634. (border = new Border {
  635. Width = 100,
  636. Height = 37.94318181818182,
  637. UseLayoutRounding = false
  638. })
  639. }
  640. }
  641. }
  642. };
  643. innerPresenter.UpdateChild();
  644. outerPresenter.UpdateChild();
  645. outerPresenter.Measure(new Size(100, 170.0568181818182));
  646. outerPresenter.Arrange(new Rect(0, 0, 100, 170.0568181818182));
  647. border.BringIntoView();
  648. Assert.Equal(new Vector(0, 323.20454545454544), outerPresenter.Offset);
  649. Assert.Equal(new Vector(0, 0), innerPresenter.Offset);
  650. }
  651. private class TestControl : Control
  652. {
  653. public Size AvailableSize { get; private set; }
  654. protected override Size MeasureOverride(Size availableSize)
  655. {
  656. AvailableSize = availableSize;
  657. return new Size(150, 150);
  658. }
  659. }
  660. }
  661. }