public void VerifyCorrectionsInNonScrollableDirection() { ItemsRepeater rootRepeater = null; ScrollViewer scrollViewer = null; ItemsRepeaterScrollHost scrollhost = null; ManualResetEvent viewChanged = new ManualResetEvent(false); RunOnUIThread.Execute(() => { scrollhost = (ItemsRepeaterScrollHost)XamlReader.Load( @"<controls:ItemsRepeaterScrollHost Width='400' Height='600' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:controls='using:Microsoft.UI.Xaml.Controls'> <ScrollViewer Width='400' Height='400' x:Name='scrollviewer'> <controls:ItemsRepeater x:Name='repeater'> <DataTemplate> <StackPanel> <controls:ItemsRepeater ItemsSource='{Binding}'> <controls:ItemsRepeater.Layout> <controls:StackLayout Orientation='Horizontal' /> </controls:ItemsRepeater.Layout> </controls:ItemsRepeater> </StackPanel> </DataTemplate> </controls:ItemsRepeater> </ScrollViewer> </controls:ItemsRepeaterScrollHost>"); rootRepeater = (ItemsRepeater)scrollhost.FindName("repeater"); scrollViewer = (ScrollViewer)scrollhost.FindName("scrollviewer"); scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChanged.Set(); } }; List <List <int> > items = new List <List <int> >(); for (int i = 0; i < 100; i++) { items.Add(Enumerable.Range(0, 4).ToList()); } rootRepeater.ItemsSource = items; Content = scrollhost; }); // scroll down several times and validate no crash for (int i = 1; i < 5; i++) { IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { scrollViewer.ChangeView(null, i * 200, null); }); Verify.IsTrue(viewChanged.WaitOne(DefaultWaitTimeInMS)); viewChanged.Reset(); } }
public void BasicMarginAndAlignment() { if (PlatformConfiguration.IsOsVersionGreaterThan(OSVersion.Redstone4)) { //BUGBUG Bug 19277312: MUX Scroller tests fail on RS5_Release return; } if (!PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone2)) { // Skipping this test on pre-RS2 since it uses Visual's Translation property. return; } const float c_smallZoomFactor = 0.15f; const double c_Margin = 40.0; Scroller scroller = null; Rectangle rectangleScrollerContent = null; AutoResetEvent scrollerLoadedEvent = new AutoResetEvent(false); float horizontalOffset = 0.0f; float verticalOffset = 0.0f; float zoomFactor = 1.0f; Compositor compositor = null; RunOnUIThread.Execute(() => { rectangleScrollerContent = new Rectangle(); scroller = new Scroller(); SetupDefaultUI(scroller, rectangleScrollerContent, scrollerLoadedEvent); Log.Comment("Adding positive Margin to Scroller.Content"); rectangleScrollerContent.Margin = new Thickness(c_Margin); compositor = Window.Current.Compositor; }); WaitForEvent("Waiting for Loaded event", scrollerLoadedEvent); // Jump to absolute small zoomFactor to make the content smaller than the viewport. ChangeZoomFactor(scroller, c_smallZoomFactor, 0.0f, 0.0f, ScrollerViewKind.Absolute, ScrollerViewChangeKind.DisableAnimation); RunOnUIThread.Execute(() => { Log.Comment("Covering Stretch/Strech alignments"); Verify.AreEqual(rectangleScrollerContent.HorizontalAlignment, HorizontalAlignment.Stretch); Verify.AreEqual(rectangleScrollerContent.VerticalAlignment, VerticalAlignment.Stretch); }); SpyTranslationAndScale(scroller, compositor, out horizontalOffset, out verticalOffset, out zoomFactor); Verify.IsTrue(Math.Abs(horizontalOffset - 20.0f) < c_defaultOffsetResultTolerance); Verify.IsTrue(Math.Abs(verticalOffset - 15.0f) < c_defaultOffsetResultTolerance); Verify.AreEqual(zoomFactor, c_smallZoomFactor); RunOnUIThread.Execute(() => { Log.Comment("Covering Left/Top alignments"); rectangleScrollerContent.HorizontalAlignment = HorizontalAlignment.Left; rectangleScrollerContent.VerticalAlignment = VerticalAlignment.Top; }); SpyTranslationAndScale(scroller, compositor, out horizontalOffset, out verticalOffset, out zoomFactor); Verify.IsTrue(Math.Abs(horizontalOffset + 34.0f) < c_defaultOffsetResultTolerance); Verify.IsTrue(Math.Abs(verticalOffset + 34.0f) < c_defaultOffsetResultTolerance); Verify.AreEqual(zoomFactor, c_smallZoomFactor); RunOnUIThread.Execute(() => { Log.Comment("Covering Right/Bottom alignments"); rectangleScrollerContent.HorizontalAlignment = HorizontalAlignment.Right; rectangleScrollerContent.VerticalAlignment = VerticalAlignment.Bottom; }); SpyTranslationAndScale(scroller, compositor, out horizontalOffset, out verticalOffset, out zoomFactor); Verify.IsTrue(Math.Abs(horizontalOffset - 74.0f) < c_defaultOffsetResultTolerance); Verify.IsTrue(Math.Abs(verticalOffset - 64.0f) < c_defaultOffsetResultTolerance); Verify.AreEqual(zoomFactor, c_smallZoomFactor); RunOnUIThread.Execute(() => { Log.Comment("Covering Center/Center alignments"); rectangleScrollerContent.HorizontalAlignment = HorizontalAlignment.Center; rectangleScrollerContent.VerticalAlignment = VerticalAlignment.Center; }); SpyTranslationAndScale(scroller, compositor, out horizontalOffset, out verticalOffset, out zoomFactor); Verify.IsTrue(Math.Abs(horizontalOffset - 20.0f) < c_defaultOffsetResultTolerance); Verify.IsTrue(Math.Abs(verticalOffset - 15.0f) < c_defaultOffsetResultTolerance); Verify.AreEqual(zoomFactor, c_smallZoomFactor); }
public void ImageWithConstrainedHeight() { if (PlatformConfiguration.IsOsVersionGreaterThan(OSVersion.Redstone4)) { //BUGBUG Bug 19277312: MUX Scroller tests fail on RS5_Release return; } if (!PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone2)) { // Skipping this test on pre-RS2 since it uses Visual's Translation property. return; } const float c_smallZoomFactor = 0.5f; const float c_largeZoomFactor = 2.0f; const double c_imageWidth = 250.0; const double c_topMargin = 40.0; const double c_bottomMargin = 10.0; Scroller scroller = null; Image imageScrollerContent = null; AutoResetEvent scrollerLoadedEvent = new AutoResetEvent(false); Compositor compositor = null; RunOnUIThread.Execute(() => { imageScrollerContent = new Image(); scroller = new Scroller(); Uri uri = new Uri("ms-appx:/Assets/ingredient3.png"); Verify.IsNotNull(uri); imageScrollerContent.Source = new BitmapImage(uri); imageScrollerContent.Margin = new Thickness(0, c_topMargin, 0, c_bottomMargin); scroller.Content = imageScrollerContent; scroller.Background = new Media.SolidColorBrush(Colors.Chartreuse); SetupDefaultUI(scroller, rectangleScrollerContent: null, scrollerLoadedEvent: scrollerLoadedEvent); // Constraining the Image height and making the Scroller smaller than the Image imageScrollerContent.Width = c_imageWidth; scroller.ContentOrientation = ContentOrientation.Horizontal; compositor = Window.Current.Compositor; }); WaitForEvent("Waiting for Loaded event", scrollerLoadedEvent); // Jump to absolute small zoomFactor to make the content smaller than the viewport. ChangeZoomFactor(scroller, c_smallZoomFactor, 0.0f, 0.0f, ScrollerViewKind.Absolute, ScrollerViewChangeKind.DisableAnimation); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Stretch, expectedHorizontalOffset: (float)(c_defaultUIScrollerWidth - c_imageWidth * c_smallZoomFactor) / 2.0f, // 87.5 expectedMinPosition: (float)(-c_defaultUIScrollerHeight * c_smallZoomFactor / 2.0), // -50 expectedZoomFactor: c_smallZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Top, expectedHorizontalOffset: (float)(c_defaultUIScrollerWidth - c_imageWidth * c_smallZoomFactor) / 2.0f, // 87.5 expectedMinPosition: 0.0f, expectedZoomFactor: c_smallZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Bottom, expectedHorizontalOffset: (float)(c_defaultUIScrollerWidth - c_imageWidth * c_smallZoomFactor) / 2.0f, // 87.5 expectedMinPosition: (float)(-c_defaultUIScrollerHeight * c_smallZoomFactor), // -100 expectedZoomFactor: c_smallZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Center, expectedHorizontalOffset: (float)(c_defaultUIScrollerWidth - c_imageWidth * c_smallZoomFactor) / 2.0f, // 87.5 expectedMinPosition: (float)(-c_defaultUIScrollerHeight * c_smallZoomFactor / 2.0), // -50 expectedZoomFactor: c_smallZoomFactor); // Jump to absolute large zoomFactor to make the content larger than the viewport. ChangeZoomFactor(scroller, c_largeZoomFactor, 0.0f, 0.0f, ScrollerViewKind.Absolute, ScrollerViewChangeKind.DisableAnimation); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Stretch, expectedHorizontalOffset: 0.0f, expectedMinPosition: 0.0f, expectedZoomFactor: c_largeZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Top, expectedHorizontalOffset: 0.0f, expectedMinPosition: 0.0f, expectedZoomFactor: c_largeZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Bottom, expectedHorizontalOffset: 0.0f, expectedMinPosition: 0.0f, expectedZoomFactor: c_largeZoomFactor); ValidateContentWithConstrainedHeight( compositor, scroller, content: imageScrollerContent, verticalAlignment: VerticalAlignment.Center, expectedHorizontalOffset: 0.0f, expectedMinPosition: 0.0f, expectedZoomFactor: c_largeZoomFactor); }
public void VerifyVSMStatesForPhotosAndInitials() { PersonPicture personPicture = null; TextBlock initialsTextBlock = null; RunOnUIThread.Execute(() => { personPicture = new PersonPicture(); MUXControlsTestApp.App.TestContentRoot = personPicture; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { initialsTextBlock = (TextBlock)VisualTreeUtils.FindVisualChildByName(personPicture, "InitialsTextBlock"); personPicture.IsGroup = true; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(initialsTextBlock.FontFamily.Source, "Segoe MDL2 Assets"); Verify.AreEqual(initialsTextBlock.Text, "\xE716"); personPicture.IsGroup = false; personPicture.Initials = "JS"; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(initialsTextBlock.FontFamily.Source, "Segoe UI"); Verify.AreEqual(initialsTextBlock.Text, "JS"); personPicture.Initials = ""; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(initialsTextBlock.FontFamily.Source, "Segoe MDL2 Assets"); Verify.AreEqual(initialsTextBlock.Text, "\xE77B"); // Make sure that custom FontFamily takes effect after the control is created // and also goes back to the MDL2 font after setting IsGroup = true. personPicture.FontFamily = new FontFamily("Segoe UI Emoji"); personPicture.Initials = "👍"; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(initialsTextBlock.FontFamily.Source, "Segoe UI Emoji"); Verify.AreEqual(initialsTextBlock.Text, "👍"); personPicture.IsGroup = true; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(initialsTextBlock.FontFamily.Source, "Segoe MDL2 Assets"); Verify.AreEqual(initialsTextBlock.Text, "\xE716"); }); }
public void VerifySingleSelection() { string navItemPresenter1CurrentState = string.Empty; string navItemPresenter2CurrentState = string.Empty; NavigationView navView = null; NavigationViewItem menuItem1 = null; NavigationViewItem menuItem2 = null; RunOnUIThread.Execute(() => { navView = new NavigationView(); Content = navView; menuItem1 = new NavigationViewItem(); menuItem2 = new NavigationViewItem(); menuItem1.Content = "Item 1"; menuItem2.Content = "Item 2"; navView.MenuItems.Add(menuItem1); navView.MenuItems.Add(menuItem2); navView.Width = 1008; // forces the control into Expanded mode so that the menu renders Content.UpdateLayout(true); var menuItemLayoutRoot = VisualTreeHelper.GetChild(menuItem1, 0) as FrameworkElement; var navItemPresenter = VisualTreeHelper.GetChild(menuItemLayoutRoot, 0) as FrameworkElement; var navItemPresenterLayoutRoot = VisualTreeHelper.GetChild(navItemPresenter, 0) as FrameworkElement; var statesGroups = VisualStateManager.GetVisualStateGroups(navItemPresenterLayoutRoot); foreach (VisualStateGroup visualStateGroup in statesGroups) { Log.Comment($"VisualStateGroup1: Name={visualStateGroup.Name}, CurrentState={visualStateGroup.CurrentState.Name}"); visualStateGroup.CurrentStateChanged += (object sender, VisualStateChangedEventArgs e) => { Log.Comment($"VisualStateChangedEventArgs1: Name={e.Control.Name}, OldState={e.OldState.Name}, NewState={e.NewState.Name}"); navItemPresenter1CurrentState = e.NewState.Name; }; } menuItemLayoutRoot = VisualTreeHelper.GetChild(menuItem2, 0) as FrameworkElement; navItemPresenter = VisualTreeHelper.GetChild(menuItemLayoutRoot, 0) as FrameworkElement; navItemPresenterLayoutRoot = VisualTreeHelper.GetChild(navItemPresenter, 0) as FrameworkElement; statesGroups = VisualStateManager.GetVisualStateGroups(navItemPresenterLayoutRoot); foreach (VisualStateGroup visualStateGroup in statesGroups) { Log.Comment($"VisualStateGroup2: Name={visualStateGroup.Name}, CurrentState={visualStateGroup.CurrentState.Name}"); visualStateGroup.CurrentStateChanged += (object sender, VisualStateChangedEventArgs e) => { Log.Comment($"VisualStateChangedEventArgs2: Name={e.Control.Name}, OldState={e.OldState.Name}, NewState={e.NewState.Name}"); navItemPresenter2CurrentState = e.NewState.Name; }; } Verify.IsFalse(menuItem1.IsSelected); Verify.IsFalse(menuItem2.IsSelected); Verify.AreEqual(null, navView.SelectedItem); menuItem1.IsSelected = true; Content.UpdateLayout(); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual("Selected", navItemPresenter1CurrentState); Verify.AreEqual(string.Empty, navItemPresenter2CurrentState); Verify.IsTrue(menuItem1.IsSelected); Verify.IsFalse(menuItem2.IsSelected); Verify.AreEqual(menuItem1, navView.SelectedItem); menuItem2.IsSelected = true; Content.UpdateLayout(); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual("Normal", navItemPresenter1CurrentState); Verify.AreEqual("Selected", navItemPresenter2CurrentState); Verify.IsTrue(menuItem2.IsSelected); Verify.IsFalse(menuItem1.IsSelected, "MenuItem1 should have been deselected when MenuItem2 was selected"); Verify.AreEqual(menuItem2, navView.SelectedItem); }); }
public void ColorPickerTest() { RunOnUIThread.Execute(() => { ColorPicker colorPicker = new ColorPicker(); Verify.IsNotNull(colorPicker); Verify.AreEqual(Colors.White, colorPicker.Color); Verify.IsNull(colorPicker.PreviousColor); Verify.IsFalse(colorPicker.IsAlphaEnabled); Verify.IsTrue(colorPicker.IsColorSpectrumVisible); Verify.IsTrue(colorPicker.IsColorPreviewVisible); Verify.IsTrue(colorPicker.IsColorSliderVisible); Verify.IsTrue(colorPicker.IsAlphaSliderVisible); Verify.IsFalse(colorPicker.IsMoreButtonVisible); Verify.IsTrue(colorPicker.IsColorChannelTextInputVisible); Verify.IsTrue(colorPicker.IsAlphaTextInputVisible); Verify.IsTrue(colorPicker.IsHexInputVisible); Verify.AreEqual(0, colorPicker.MinHue); Verify.AreEqual(359, colorPicker.MaxHue); Verify.AreEqual(0, colorPicker.MinSaturation); Verify.AreEqual(100, colorPicker.MaxSaturation); Verify.AreEqual(0, colorPicker.MinValue); Verify.AreEqual(100, colorPicker.MaxValue); Verify.AreEqual(ColorSpectrumShape.Box, colorPicker.ColorSpectrumShape); Verify.AreEqual(ColorSpectrumComponents.HueSaturation, colorPicker.ColorSpectrumComponents); // Clamping the min and max properties changes the color value, // so let's test this new value before we change those. colorPicker.Color = Colors.Green; Verify.AreEqual(Colors.Green, colorPicker.Color); colorPicker.PreviousColor = Colors.Red; colorPicker.IsAlphaEnabled = true; colorPicker.IsColorSpectrumVisible = false; colorPicker.IsColorPreviewVisible = false; colorPicker.IsColorSliderVisible = false; colorPicker.IsAlphaSliderVisible = false; colorPicker.IsMoreButtonVisible = true; colorPicker.IsColorChannelTextInputVisible = false; colorPicker.IsAlphaTextInputVisible = false; colorPicker.IsHexInputVisible = false; colorPicker.MinHue = 10; colorPicker.MaxHue = 300; colorPicker.MinSaturation = 10; colorPicker.MaxSaturation = 90; colorPicker.MinValue = 10; colorPicker.MaxValue = 90; colorPicker.ColorSpectrumShape = ColorSpectrumShape.Ring; colorPicker.ColorSpectrumComponents = ColorSpectrumComponents.HueValue; Verify.AreNotEqual(Colors.Green, colorPicker.Color); Verify.AreEqual(Colors.Red, colorPicker.PreviousColor); Verify.IsTrue(colorPicker.IsAlphaEnabled); Verify.IsFalse(colorPicker.IsColorSpectrumVisible); Verify.IsFalse(colorPicker.IsColorPreviewVisible); Verify.IsFalse(colorPicker.IsColorSliderVisible); Verify.IsFalse(colorPicker.IsAlphaSliderVisible); Verify.IsTrue(colorPicker.IsMoreButtonVisible); Verify.IsFalse(colorPicker.IsColorChannelTextInputVisible); Verify.IsFalse(colorPicker.IsAlphaTextInputVisible); Verify.IsFalse(colorPicker.IsHexInputVisible); Verify.AreEqual(10, colorPicker.MinHue); Verify.AreEqual(300, colorPicker.MaxHue); Verify.AreEqual(10, colorPicker.MinSaturation); Verify.AreEqual(90, colorPicker.MaxSaturation); Verify.AreEqual(10, colorPicker.MinValue); Verify.AreEqual(90, colorPicker.MaxValue); Verify.AreEqual(ColorSpectrumShape.Ring, colorPicker.ColorSpectrumShape); Verify.AreEqual(ColorSpectrumComponents.HueValue, colorPicker.ColorSpectrumComponents); }); }
public void ValidateDataTemplateSelectorAsItemTemplate() { RunOnUIThread.Execute(() => { var dataTemplateOdd = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <TextBlock Text='{Binding}' Height='30' /> </DataTemplate>"); var dataTemplateEven = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <TextBlock Text='{Binding}' Height='40' /> </DataTemplate>"); ItemsRepeater repeater = null; const int numItems = 10; var selector = new MySelector() { TemplateOdd = dataTemplateOdd, TemplateEven = dataTemplateEven }; Content = CreateAndInitializeRepeater ( itemsSource: Enumerable.Range(0, numItems), elementFactory: selector, layout: new StackLayout(), repeater: ref repeater ); Content.UpdateLayout(); Verify.AreEqual(numItems, VisualTreeHelper.GetChildrenCount(repeater)); for (int i = 0; i < numItems; i++) { var element = (TextBlock)repeater.TryGetElement(i); Verify.AreEqual(i.ToString(), element.Text); Verify.AreEqual(i % 2 == 0 ? 40 : 30, element.Height); } repeater.ItemsSource = null; Content.UpdateLayout(); // In versions below RS5 we faked the recycling behaivor on data template // so we can get to the recycle pool that we addded internally in ItemsRepeater. if (PlatformConfiguration.IsOSVersionLessThan(OSVersion.Redstone5)) { // All the created items should be in the recycle pool now. var oddPool = RecyclePool.GetPoolInstance(dataTemplateOdd); var oddElements = GetAllElementsFromPool(oddPool); Verify.AreEqual(5, oddElements.Count); foreach (var element in oddElements) { Verify.AreEqual(30, ((TextBlock)element).Height); } var evenPool = RecyclePool.GetPoolInstance(dataTemplateEven); var evenElements = GetAllElementsFromPool(evenPool); Verify.AreEqual(5, evenElements.Count); foreach (var element in evenElements) { Verify.AreEqual(40, ((TextBlock)element).Height); } } }); }
public void CanPinFocusedElements() { // Setup a grouped repeater scenario with two groups each containing two items. var data = new ObservableCollection <ObservableCollection <string> >(Enumerable .Range(0, 2) .Select(i => new ObservableCollection <string>(Enumerable .Range(0, 2) .Select(j => string.Format("Item #{0}.{1}", i, j))))); List <ContentControl>[] itemElements = null; ItemsRepeater[] innerRepeaters = null; List <StackPanel> groupElements = null; ItemsRepeater rootRepeater = null; var gotFocus = new ManualResetEvent(false); RunOnUIThread.Execute(() => { itemElements = new[] { Enumerable.Range(0, 2).Select(i => new ContentControl()).ToList(), Enumerable.Range(0, 2).Select(i => new ContentControl()).ToList() }; itemElements[0][0].GotFocus += delegate { gotFocus.Set(); }; innerRepeaters = Enumerable.Range(0, 2).Select(i => CreateRepeater( MockItemsSource.CreateDataSource(data[i], supportsUniqueIds: false), MockElementFactory.CreateElementFactory(itemElements[i]))).ToArray(); groupElements = Enumerable.Range(0, 2).Select(i => { var panel = new StackPanel(); panel.Children.Add(new ContentControl()); panel.Children.Add(innerRepeaters[i]); return(panel); }).ToList(); rootRepeater = CreateRepeater( MockItemsSource.CreateDataSource(data, supportsUniqueIds: false), MockElementFactory.CreateElementFactory(groupElements)); Content = rootRepeater; rootRepeater.UpdateLayout(); itemElements[0][0].Focus(FocusState.Keyboard); }); Verify.IsTrue(gotFocus.WaitOne(DefaultWaitTimeInMS), "Waiting for focus event on the first element of the first group."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Recycle focused element 0.0 and validate it's still realized because it is pinned."); { var ctx = (VirtualizingLayoutContext)innerRepeaters[0].Tag; ctx.RecycleElement(itemElements[0][0]); Verify.AreEqual(0, innerRepeaters[0].GetElementIndex(itemElements[0][0])); } Log.Comment("Recycle element 0.1 and validate it's no longer realized because it is not pinned."); { var ctx = (VirtualizingLayoutContext)innerRepeaters[0].Tag; ctx.RecycleElement(itemElements[0][1]); Verify.AreEqual(-1, innerRepeaters[0].GetElementIndex(itemElements[0][1])); } Log.Comment("Recycle group 0 and validate it's still realized because one of its items is pinned."); { var ctx = (VirtualizingLayoutContext)rootRepeater.Tag; ctx.RecycleElement(groupElements[0]); Verify.AreEqual(0, rootRepeater.GetElementIndex(groupElements[0])); } itemElements[1][1].GotFocus += delegate { gotFocus.Set(); }; itemElements[1][1].Focus(FocusState.Keyboard); }); Verify.IsTrue(gotFocus.WaitOne(DefaultWaitTimeInMS), "Waiting for focus event on the second element of the second group."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment(@"Move focus to item 1.1 and validate item 0.0 and group 0 are recycled because the only thing keeping them around is the fact that item 0.0 was focus pinned"); { ((VirtualizingLayoutContext)rootRepeater.Tag).RecycleElement(groupElements[0]); ((VirtualizingLayoutContext)innerRepeaters[0].Tag).RecycleElement(itemElements[0][0]); Verify.AreEqual(-1, rootRepeater.GetElementIndex(groupElements[0])); Verify.AreEqual(-1, innerRepeaters[0].GetElementIndex(itemElements[0][0])); Verify.AreEqual(1, innerRepeaters[0].GetElementIndex(itemElements[1][1])); } Log.Comment(@"Delete item 1.1 from the data. This will force the element to get recycled even if it's pinned."); { data[1].RemoveAt(1); rootRepeater.UpdateLayout(); Verify.AreEqual(-1, innerRepeaters[1].GetElementIndex(itemElements[1][1])); } }); }
public void ExpanderAutomationPeerTest() { RunOnUIThread.Execute(() => { var root = (StackPanel)XamlReader.Load( @"<StackPanel xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:primitives='using:Microsoft.UI.Xaml.Controls.Primitives' xmlns:controls='using:Microsoft.UI.Xaml.Controls'> <controls:Expander x:Name ='ExpandedExpander' AutomationProperties.Name='ExpandedExpander' IsExpanded='True' Margin='12' HorizontalAlignment='Left'> <controls:Expander.Header> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width='80'/> </Grid.ColumnDefinitions> <StackPanel Margin='0,14,0,16'> <TextBlock AutomationProperties.Name='test' Text='This expander is expanded by default.' Margin='0,0,0,4' /> <TextBlock Text='This is the second line of text.' /> </StackPanel> <ToggleSwitch Grid.Column='1'/> </Grid> </controls:Expander.Header> <Button AutomationProperties.AutomationId = 'ExpandedExpanderContent'> Content </Button> </controls:Expander> </StackPanel>"); Content = root; Content.UpdateLayout(); var expander = VisualTreeHelper.GetChild(root, 0) as Expander; expander.IsExpanded = true; Content.UpdateLayout(); var grid = VisualTreeHelper.GetChild(expander, 0); var toggleButton = VisualTreeHelper.GetChild(grid, 0); var toggleButtonGrid = VisualTreeHelper.GetChild(toggleButton, 0); var contentPresenter = VisualTreeHelper.GetChild(toggleButtonGrid, 0); var grid2 = VisualTreeHelper.GetChild(contentPresenter, 0); var stackPanel = VisualTreeHelper.GetChild(grid2, 0); var textBlock1 = VisualTreeHelper.GetChild(stackPanel, 0) as TextBlock; var textBlock2 = VisualTreeHelper.GetChild(stackPanel, 1) as TextBlock; var toggleSwitch = VisualTreeHelper.GetChild(grid2, 1) as ToggleSwitch; var border = VisualTreeHelper.GetChild(grid, 1); var expanderContentBorder = VisualTreeHelper.GetChild(border, 0); var expanderContentContentPresenter = VisualTreeHelper.GetChild(expanderContentBorder, 0); var button = VisualTreeHelper.GetChild(expanderContentContentPresenter, 0) as Button; Verify.AreEqual("ExpandedExpander", AutomationProperties.GetName(expander)); // Verify ExpandedExpander header content are included in the accessibility tree Verify.AreEqual(AutomationProperties.GetAccessibilityView(textBlock1), AccessibilityView.Content); Verify.AreEqual(AutomationProperties.GetAccessibilityView(textBlock2), AccessibilityView.Content); Verify.AreEqual(AutomationProperties.GetAccessibilityView(toggleSwitch), AccessibilityView.Content); // Verify ExpandedExpander content is included in the accessibility tree Verify.AreEqual(AutomationProperties.GetAccessibilityView(button), AccessibilityView.Content); expander.IsExpanded = false; Content.UpdateLayout(); // Verify ExpandedExpander content is not included in the accessibility tree and not readable once collapsed Verify.AreNotEqual(AutomationProperties.GetAccessibilityView(button), AccessibilityView.Raw); }); }
public void ValidateElementIndexChangedEventOnStableReset() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSourceWithUniqueId(Enumerable.Range(0, 10).ToList())); var repeater = SetupRepeater(dataSource); RunOnUIThread.Execute(() => { List <int> preparedIndices = new List <int>(); List <int> clearedIndices = new List <int>(); List <KeyValuePair <int, int> > changedIndices = new List <KeyValuePair <int, int> >(); repeater.ElementPrepared += (sender, args) => { preparedIndices.Add(args.Index); }; repeater.ElementClearing += (sender, args) => { clearedIndices.Add(sender.GetElementIndex(args.Element)); }; repeater.ElementIndexChanged += (sender, args) => { changedIndices.Add(new KeyValuePair <int, int>(args.OldIndex, args.NewIndex)); }; Log.Comment("(UniqueId Reset) Insert in realized range: Inserting 1 item at index 1"); dataSource.Insert(index: 1, count: 1, reset: true, valueStart: 2000); repeater.UpdateLayout(); Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(1, preparedIndices[0]); Verify.AreEqual(1, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 2))); foreach (var ch in changedIndices) { Log.Comment("Changed " + ch.Key + " " + ch.Value); } Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(2, clearedIndices[0]); preparedIndices.Clear(); clearedIndices.Clear(); changedIndices.Clear(); Log.Comment("(UniqueId Reset) Remove in realized range: Removing 1 item at index 0"); dataSource.Remove(index: 0, count: 1, reset: true); repeater.UpdateLayout(); Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(0, clearedIndices[0]); foreach (var ch in changedIndices) { Log.Comment("Changed " + ch.Key + " " + ch.Value); } Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(2, preparedIndices[0]); Verify.AreEqual(2, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 0))); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(2, 1))); }); }
public void ValidateElementClearingOrderFromFlowLayout() { ItemsSourceView dataSource = null; RunOnUIThread.Execute(() => dataSource = new ItemsSourceView(Enumerable.Range(0, 15).ToList())); ScrollViewer scrollViewer = null; var repeater = SetupRepeater(dataSource, null /*layout*/, out scrollViewer); List <int> clearedIndices = new List <int>(); var viewChangedEvent = new ManualResetEvent(false); RunOnUIThread.Execute(() => { scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChangedEvent.Set(); } }; repeater.Layout = new StackLayout(); repeater.ElementPrepared += (sender, args) => { ((FrameworkElement)args.Element).Height = 20; }; repeater.UpdateLayout(); repeater.ElementClearing += (sender, args) => { int index = repeater.GetElementIndex(args.Element); Log.Comment("Clearing.." + index); clearedIndices.Add(index); }; scrollViewer.ChangeView(null, 100.0, null, disableAnimation: true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { // Validate order is 0, 1, 2, 3 for (int i = 0; i < 4; i++) { Verify.AreEqual(i, clearedIndices[i]); } clearedIndices.Clear(); viewChangedEvent.Reset(); scrollViewer.ChangeView(null, 0.0, null, disableAnimation: true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { // Validate order is backwards 14, 13, 12, 11 for (int i = 0; i < 4; i++) { Verify.AreEqual(14 - i, clearedIndices[i]); } }); }
public void ValidateElementEvents() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); var repeater = SetupRepeater(dataSource); RunOnUIThread.Execute(() => { List <int> preparedIndices = new List <int>(); List <int> clearedIndices = new List <int>(); List <KeyValuePair <int, int> > changedIndices = new List <KeyValuePair <int, int> >(); repeater.ElementPrepared += (sender, args) => { preparedIndices.Add(args.Index); }; repeater.ElementClearing += (sender, args) => { clearedIndices.Add(sender.GetElementIndex(args.Element)); }; repeater.ElementIndexChanged += (sender, args) => { changedIndices.Add(new KeyValuePair <int, int>(args.OldIndex, args.NewIndex)); }; Log.Comment("Insert in realized range: Inserting 1 item at index 1"); dataSource.Insert(index: 1, count: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(1, preparedIndices[0]); Verify.AreEqual(2, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 2))); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(2, 3))); Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(3, clearedIndices[0]); preparedIndices.Clear(); clearedIndices.Clear(); changedIndices.Clear(); Log.Comment("Remove in realized range: Removing 1 item at index 0"); dataSource.Remove(index: 0, count: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(0, clearedIndices[0]); if (PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone5)) { Verify.AreEqual(0, preparedIndices.Count); } else { Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(2, preparedIndices[0]); } Verify.AreEqual(2, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 0))); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(2, 1))); }); }
public void CanReuseElementsDuringUniqueIdReset() { var data = new WinRTCollection(Enumerable.Range(0, 2).Select(i => string.Format("Item #{0}", i))); List <UIElement> mapping = null; ItemsRepeater repeater = null; MockElementFactory elementFactory = null; ContentControl focusedElement = null; RunOnUIThread.Execute(() => { mapping = new List <UIElement> { new ContentControl(), new ContentControl() }; repeater = CreateRepeater( MockItemsSource.CreateDataSource(data, supportsUniqueIds: true), MockElementFactory.CreateElementFactory(mapping)); elementFactory = (MockElementFactory)repeater.ItemTemplate; Content = repeater; repeater.UpdateLayout(); focusedElement = (ContentControl)repeater.TryGetElement(1); focusedElement.Focus(FocusState.Keyboard); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { elementFactory.ValidateGetElementCalls( new MockElementFactory.GetElementCallInfo(0, repeater), new MockElementFactory.GetElementCallInfo(1, repeater)); elementFactory.ValidateRecycleElementCalls(); data.ResetWith(new[] { data[0], "New item" }); Verify.AreEqual(0, repeater.GetElementIndex(mapping[0])); Verify.AreEqual(1, repeater.GetElementIndex(mapping[1])); Verify.IsNull(repeater.TryGetElement(0)); Verify.IsNull(repeater.TryGetElement(1)); elementFactory.ValidateGetElementCalls(/* GetElement should not be called */); elementFactory.ValidateRecycleElementCalls(/* RecycleElement should not be called */); mapping[1] = new ContentControl(); // For "New Item" repeater.UpdateLayout(); Verify.AreEqual(0, repeater.GetElementIndex(mapping[0])); Verify.AreEqual(1, repeater.GetElementIndex(mapping[1])); Verify.AreEqual(mapping[0], repeater.TryGetElement(0)); Verify.AreEqual(mapping[1], repeater.TryGetElement(1)); elementFactory.ValidateGetElementCalls( new MockElementFactory.GetElementCallInfo(1, repeater)); elementFactory.ValidateRecycleElementCalls( new MockElementFactory.RecycleElementCallInfo(focusedElement, repeater)); // If the focused element survived the reset, we will keep focus on it. If not, we // try to find one based on the index. In this case, the focused element (index 1) // got recycled, and we still have index 1 after the stable reset, so the new index 1 // will get focused. Note that recycling the elements to view generator in the case of // stable reset happens during the arrange, so by that time we will have pulled elements // from the stable reset pool and maybe created some new elements as well. int index = repeater.GetElementIndex(focusedElement); Log.Comment("focused index " + index); Verify.AreEqual(mapping[1], FocusManager.GetFocusedElement()); }); }
public void VerifyStoreScenarioCache() { ItemsRepeater rootRepeater = null; RunOnUIThread.Execute(() => { var scrollhost = (ItemsRepeaterScrollHost)XamlReader.Load( @" <controls:ItemsRepeaterScrollHost Width='400' Height='200' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:controls='using:Microsoft.UI.Xaml.Controls'> <controls:ItemsRepeaterScrollHost.Resources> <DataTemplate x:Key='ItemTemplate' > <TextBlock Text='{Binding}' Height='100' Width='100'/> </DataTemplate> <DataTemplate x:Key='GroupTemplate'> <StackPanel> <TextBlock Text='{Binding}' /> <controls:ItemsRepeaterScrollHost> <ScrollViewer HorizontalScrollMode='Enabled' VerticalScrollMode='Disabled' HorizontalScrollBarVisibility='Auto' VerticalScrollBarVisibility='Hidden'> <controls:ItemsRepeater ItemTemplate='{StaticResource ItemTemplate}' ItemsSource='{Binding}'> <controls:ItemsRepeater.Layout> <controls:StackLayout Orientation='Horizontal' /> </controls:ItemsRepeater.Layout> </controls:ItemsRepeater> </ScrollViewer> </controls:ItemsRepeaterScrollHost> </StackPanel> </DataTemplate> </controls:ItemsRepeaterScrollHost.Resources> <ScrollViewer x:Name='scrollviewer'> <controls:ItemsRepeater x:Name='rootRepeater' ItemTemplate='{StaticResource GroupTemplate}'/> </ScrollViewer> </controls:ItemsRepeaterScrollHost>"); rootRepeater = (ItemsRepeater)scrollhost.FindName("rootRepeater"); List <List <int> > items = new List <List <int> >(); for (int i = 0; i < 100; i++) { items.Add(Enumerable.Range(0, 4).ToList()); } rootRepeater.ItemsSource = items; Content = scrollhost; }); IdleSynchronizer.Wait(); // Verify that first items outside the visible range but in the realized range // for the inner of the nested repeaters are realized. RunOnUIThread.Execute(() => { // Group2 will be outside the visible range but within the realized range. var group2 = rootRepeater.TryGetElement(2) as StackPanel; Verify.IsNotNull(group2); var group2Repeater = ((ItemsRepeaterScrollHost)group2.Children[1]).ScrollViewer.Content as ItemsRepeater; Verify.IsNotNull(group2Repeater); Verify.IsNotNull(group2Repeater.TryGetElement(0)); }); }
public void CanReplaceSingleItem() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); ScrollViewer scrollViewer = null; ItemsRepeater repeater = null; var viewChangedEvent = new ManualResetEvent(false); int elementsCleared = 0; int elementsPrepared = 0; RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, ref scrollViewer); scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChangedEvent.Set(); } }; repeater.ElementPrepared += (sender, args) => { elementsPrepared++; }; repeater.ElementClearing += (sender, args) => { elementsCleared++; }; scrollViewer.ChangeView(null, 200, null, true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace before realized range."); dataSource.Replace(index: 0, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace in realized range."); elementsPrepared = 0; elementsCleared = 0; dataSource.Replace(index: 2, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, elementsPrepared); Verify.AreEqual(1, elementsCleared); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace after realized range"); dataSource.Replace(index: 8, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); }); }
public void ValidateOneScrollViewerScenario() { var realizationRects = new List <Rect>(); ScrollViewer scrollViewer = null; var viewChangeCompletedEvent = new AutoResetEvent(false); RunOnUIThread.Execute(() => { var repeater = new ItemsRepeater() { Layout = GetMonitoringLayout(new Size(500, 600), realizationRects), HorizontalCacheLength = 0.0, VerticalCacheLength = 0.0 }; scrollViewer = new ScrollViewer { Content = repeater, Width = 200, Height = 300 }; Content = scrollViewer; Content.UpdateLayout(); Verify.AreEqual(2, realizationRects.Count); Verify.AreEqual(new Rect(0, 0, 0, 0), realizationRects[0]); Verify.AreEqual(new Rect(0, 0, 200, 300), realizationRects[1]); realizationRects.Clear(); scrollViewer.ViewChanged += (Object sender, ScrollViewerViewChangedEventArgs args) => { if (!args.IsIntermediate) { viewChangeCompletedEvent.Set(); } }; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { scrollViewer.ChangeView(0.0, 100.0, null, true); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(0, 100, 200, 300), realizationRects.Last()); realizationRects.Clear(); viewChangeCompletedEvent.Reset(); scrollViewer.ChangeView(null, null, 2.0f, true); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); RunOnUIThread.Execute(() => { Verify.AreEqual( new Rect(0, 50, 100, 150), realizationRects.Last()); realizationRects.Clear(); }); }
public void ColorSpectrumTest() { RunOnUIThread.Execute(() => { ColorSpectrum colorSpectrum = new ColorSpectrum(); Verify.IsNotNull(colorSpectrum); Verify.AreEqual(Colors.White, colorSpectrum.Color); Verify.AreEqual(new Vector4() { X = 0.0f, Y = 0.0f, Z = 1.0f, W = 1.0f }, colorSpectrum.HsvColor); Verify.AreEqual(0, colorSpectrum.MinHue); Verify.AreEqual(359, colorSpectrum.MaxHue); Verify.AreEqual(0, colorSpectrum.MinSaturation); Verify.AreEqual(100, colorSpectrum.MaxSaturation); Verify.AreEqual(0, colorSpectrum.MinValue); Verify.AreEqual(100, colorSpectrum.MaxValue); Verify.AreEqual(ColorSpectrumShape.Box, colorSpectrum.Shape); Verify.AreEqual(ColorSpectrumComponents.HueSaturation, colorSpectrum.Components); colorSpectrum.Color = Colors.Green; colorSpectrum.MinHue = 10; colorSpectrum.MaxHue = 300; colorSpectrum.MinSaturation = 10; colorSpectrum.MaxSaturation = 90; colorSpectrum.MinValue = 10; colorSpectrum.MaxValue = 90; colorSpectrum.Shape = ColorSpectrumShape.Ring; colorSpectrum.Components = ColorSpectrumComponents.HueValue; Verify.AreEqual(Colors.Green, colorSpectrum.Color); // We'll probably encounter some level of rounding error here, // so we want to check that the HSV color is *close* to what's expected, // not exactly equal. Verify.IsLessThan(Math.Abs(colorSpectrum.HsvColor.X - 120.0), 0.1); Verify.IsLessThan(Math.Abs(colorSpectrum.HsvColor.Y - 1.0), 0.1); Verify.IsLessThan(Math.Abs(colorSpectrum.HsvColor.Z - 0.5), 0.1); Verify.AreEqual(10, colorSpectrum.MinHue); Verify.AreEqual(300, colorSpectrum.MaxHue); Verify.AreEqual(10, colorSpectrum.MinSaturation); Verify.AreEqual(90, colorSpectrum.MaxSaturation); Verify.AreEqual(10, colorSpectrum.MinValue); Verify.AreEqual(90, colorSpectrum.MaxValue); Verify.AreEqual(ColorSpectrumShape.Ring, colorSpectrum.Shape); Verify.AreEqual(ColorSpectrumComponents.HueValue, colorSpectrum.Components); colorSpectrum.HsvColor = new Vector4() { X = 120.0f, Y = 1.0f, Z = 1.0f, W = 1.0f }; Verify.AreEqual(Color.FromArgb(255, 0, 255, 0), colorSpectrum.Color); Verify.AreEqual(new Vector4() { X = 120.0f, Y = 1.0f, Z = 1.0f, W = 1.0f }, colorSpectrum.HsvColor); }); }
public void ValidateTwoScrollViewerScenario() { var realizationRects = new List <Rect>(); ScrollViewer horizontalScroller = null; ScrollViewer verticalScroller = null; var horizontalViewChangeCompletedEvent = new AutoResetEvent(false); var verticalViewChangeCompletedEvent = new AutoResetEvent(false); RunOnUIThread.Execute(() => { var repeater = new ItemsRepeater() { Layout = GetMonitoringLayout(new Size(500, 500), realizationRects), HorizontalCacheLength = 0.0, VerticalCacheLength = 0.0 }; horizontalScroller = new ScrollViewer { Content = repeater, HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Disabled, HorizontalScrollMode = ScrollMode.Enabled, VerticalScrollMode = ScrollMode.Disabled }; verticalScroller = new ScrollViewer { Content = horizontalScroller, Width = 200, Height = 200 }; Content = verticalScroller; Content.UpdateLayout(); Verify.AreEqual(2, realizationRects.Count); Verify.AreEqual(new Rect(0, 0, 0, 0), realizationRects[0]); Verify.AreEqual(new Rect(0, 0, 200, 200), realizationRects[1]); realizationRects.Clear(); horizontalScroller.ViewChanged += (Object sender, ScrollViewerViewChangedEventArgs args) => { if (!args.IsIntermediate) { horizontalViewChangeCompletedEvent.Set(); } }; verticalScroller.ViewChanged += (Object sender, ScrollViewerViewChangedEventArgs args) => { if (!args.IsIntermediate) { verticalViewChangeCompletedEvent.Set(); } }; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { verticalScroller.ChangeView(0.0, 100.0, null, true); }); Verify.IsTrue(verticalViewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(0, 100, 200, 200), realizationRects.Last()); realizationRects.Clear(); // Max viewport offset is (300, 300). Horizontal viewport offset // is expected to get coerced from 400 to 300. horizontalScroller.ChangeView(400.0, 100.0, null, true); }); Verify.IsTrue(horizontalViewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(300, 100, 200, 200), realizationRects.Last()); realizationRects.Clear(); }); }
// Test AlwaysUseFallback property void RunAcrylicAlwaysUseFallback() { // Need to set override flags here manually since we don't want to // unset them until worker thread actions are complete MaterialHelperTestApi.IgnoreAreEffectsFast = true; MaterialHelperTestApi.SimulateDisabledByPolicy = false; SetAcrylicBrush(AcrylicBackgroundSource.Backdrop); // Run these tests off-thread as they need to poll for brush status changes that are deferred by transition animations. Task.Run(async() => { // If we are in fallback mode already due to policy, skip the test if (await VerifyAcrylicWithPolling()) { bool[] results = { false, false, false, false }; RunOnUIThread.Execute(() => { // Set AlwaysUseFallback, verify we are using the expected fallback color _acrylicBrush.AlwaysUseFallback = true; }); results[0] = await VerifyFallbackColorWithPolling(); RunOnUIThread.Execute(() => { // Change fallback color while in fallback, veryify fallback brush is updated _acrylicBrush.FallbackColor = Colors.Purple; }); results[1] = await VerifyFallbackColorWithPolling(); RunOnUIThread.Execute(() => { // Unset AlwaysUseFallback, verify we are using acrylic again _acrylicBrush.AlwaysUseFallback = false; }); results[2] = await VerifyAcrylicWithPolling(); RunOnUIThread.Execute(() => { // Change fallback color while not in fallback, then force fallback and verify color _acrylicBrush.FallbackColor = Colors.Orange; _acrylicBrush.AlwaysUseFallback = true; }); results[3] = await VerifyFallbackColorWithPolling(); bool result = results[0] && results[1] && results[2] && results[3]; string resultString = System.String.Format("({0},{1},{2},{3})", results[0], results[1], results[2], results[3]); RunOnUIThread.Execute(() => { // Unset all override flags to avoid impacting subsequent tests MaterialHelperTestApi.IgnoreAreEffectsFast = false; MaterialHelperTestApi.SimulateDisabledByPolicy = false; TestResult.Text = "AcrylicAlwaysUseFallback: " + (result ? "Passed" : ("Failed " + resultString)); }); } else { RunOnUIThread.Execute(() => { // Unset all override flags to avoid impacting subsequent tests MaterialHelperTestApi.IgnoreAreEffectsFast = false; MaterialHelperTestApi.SimulateDisabledByPolicy = false; TestResult.Text = "AcrylicAlwaysUseFallback: Skipped"; }); } }); }
[TestProperty("Ignore", "True")] // TODO 19581880: Re-enable after investigating and fixing the test failures. #endif public void CanGrowCacheBufferWithScrollViewer() { ScrollViewer scroller = null; ItemsRepeater repeater = null; var measureRealizationRects = new List <Rect>(); var arrangeRealizationRects = new List <Rect>(); var fullCacheEvent = new ManualResetEvent(initialState: false); RunOnUIThread.Execute(() => { Log.Comment("Preparing the visual tree..."); scroller = new ScrollViewer { Width = 400, Height = 400 }; var layout = new MockVirtualizingLayout { MeasureLayoutFunc = (availableSize, context) => { var ctx = (VirtualizingLayoutContext)context; measureRealizationRects.Add(ctx.RealizationRect); return(new Size(1000, 2000)); }, ArrangeLayoutFunc = (finalSize, context) => { var ctx = (VirtualizingLayoutContext)context; arrangeRealizationRects.Add(ctx.RealizationRect); if (ctx.RealizationRect.Height == scroller.Height * (repeater.VerticalCacheLength + 1)) { fullCacheEvent.Set(); } return(finalSize); } }; repeater = new ItemsRepeater() { Layout = layout }; scroller.Content = repeater; Content = scroller; }); if (!fullCacheEvent.WaitOne(DefaultWaitTimeInMS)) { Verify.Fail("Cache full size never reached."); } IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var cacheLength = repeater.VerticalCacheLength; var expectedRealizationWindow = new Rect( -cacheLength / 2 * scroller.Width, -cacheLength / 2 * scroller.Height, (1 + cacheLength) * scroller.Width, (1 + cacheLength) * scroller.Height); Log.Comment("Validate that the realization window reached full size."); Verify.AreEqual(expectedRealizationWindow, measureRealizationRects.Last()); Verify.AreEqual(expectedRealizationWindow, arrangeRealizationRects.Last()); Log.Comment("Validate that the realization window grew by 40 pixels each time during the process."); for (int i = 2; i < measureRealizationRects.Count; ++i) { Verify.AreEqual(-40, measureRealizationRects[i].X - measureRealizationRects[i - 1].X); Verify.AreEqual(-40, measureRealizationRects[i].Y - measureRealizationRects[i - 1].Y); Verify.AreEqual(80, measureRealizationRects[i].Width - measureRealizationRects[i - 1].Width); Verify.AreEqual(80, measureRealizationRects[i].Height - measureRealizationRects[i - 1].Height); Verify.AreEqual(-40, arrangeRealizationRects[i].X - arrangeRealizationRects[i - 1].X); Verify.AreEqual(-40, arrangeRealizationRects[i].Y - arrangeRealizationRects[i - 1].Y); Verify.AreEqual(80, arrangeRealizationRects[i].Width - arrangeRealizationRects[i - 1].Width); Verify.AreEqual(80, arrangeRealizationRects[i].Height - arrangeRealizationRects[i - 1].Height); } }); }
public void ValidateRecycling() { RunOnUIThread.Execute(() => { var elementFactory = new RecyclingElementFactory() { RecyclePool = new RecyclePool(), }; elementFactory.Templates["even"] = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <TextBlock Text='even' /> </DataTemplate>"); elementFactory.Templates["odd"] = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <TextBlock Text='odd' /> </DataTemplate>"); elementFactory.SelectTemplateKey += delegate(RecyclingElementFactory sender, SelectTemplateEventArgs args) { args.TemplateKey = ((int)args.DataContext % 2 == 0) ? "even" : "odd"; }; const int numItems = 10; ItemsRepeater repeater = new ItemsRepeater() { ItemsSource = Enumerable.Range(0, numItems), ItemTemplate = elementFactory, }; var context = (ElementFactoryGetArgs)RepeaterTestHooks.CreateRepeaterElementFactoryGetArgs(); context.Parent = repeater; var clearContext = (ElementFactoryRecycleArgs)RepeaterTestHooks.CreateRepeaterElementFactoryRecycleArgs(); clearContext.Parent = repeater; // Element0 is of type even, a new one should be created context.Data = 0; var element0 = elementFactory.GetElement(context); Verify.IsNotNull(element0); Verify.AreEqual("even", (element0 as TextBlock).Text); clearContext.Element = element0; elementFactory.RecycleElement(clearContext); // Element1 is of type odd, a new one should be created context.Data = 1; var element1 = elementFactory.GetElement(context); Verify.IsNotNull(element1); Verify.AreNotSame(element0, element1); Verify.AreEqual("odd", (element1 as TextBlock).Text); clearContext.Element = element1; elementFactory.RecycleElement(clearContext); // Element0 should be recycled for element2 context.Data = 2; var element2 = elementFactory.GetElement(context); Verify.AreEqual("even", (element2 as TextBlock).Text); Verify.AreSame(element0, element2); // Element1 should be recycled for element3 context.Data = 3; var element3 = elementFactory.GetElement(context); Verify.AreEqual("odd", (element3 as TextBlock).Text); Verify.AreSame(element1, element3); }); }
[TestProperty("Ignore", "True")] // TODO 19581880: Re-enable after investigating and fixing the test failures. #endif public void CanBringIntoViewElements() { if (!PlatformConfiguration.IsOsVersionGreaterThan(OSVersion.Redstone3)) { Log.Warning("Skipping CanBringIntoViewElements because UIElement.BringIntoViewRequested was added in RS4."); return; } ScrollViewer scroller = null; ItemsRepeater repeater = null; var rootLoadedEvent = new AutoResetEvent(initialState: false); var effectiveViewChangeCompletedEvent = new AutoResetEvent(initialState: false); var viewChangeCompletedEvent = new AutoResetEvent(initialState: false); var viewChangedOffsets = new List <double>(); RunOnUIThread.Execute(() => { var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam laoreet erat vel massa rutrum, eget mollis massa vulputate. Vivamus semper augue leo, eget faucibus nulla mattis nec. Donec scelerisque lacus at dui ultricies, eget auctor ipsum placerat. Integer aliquet libero sed nisi eleifend, nec rutrum arcu lacinia. Sed a sem et ante gravida congue sit amet ut augue. Donec quis pellentesque urna, non finibus metus. Proin sed ornare tellus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam laoreet erat vel massa rutrum, eget mollis massa vulputate. Vivamus semper augue leo, eget faucibus nulla mattis nec. Donec scelerisque lacus at dui ultricies, eget auctor ipsum placerat. Integer aliquet libero sed nisi eleifend, nec rutrum arcu lacinia. Sed a sem et ante gravida congue sit amet ut augue. Donec quis pellentesque urna, non finibus metus. Proin sed ornare tellus."; var root = (Grid)XamlReader.Load(TestUtilities.ProcessTestXamlForRepo( @"<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:controls='using:Microsoft.UI.Xaml.Controls'> <Grid.Resources> <controls:StackLayout x:Name='VerticalStackLayout' /> <controls:RecyclingElementFactory x:Key='ElementFactory'> <controls:RecyclingElementFactory.RecyclePool> <controls:RecyclePool /> </controls:RecyclingElementFactory.RecyclePool> <DataTemplate x:Key='ItemTemplate'> <Border Background='LightGray' Margin ='5'> <TextBlock Text='{Binding}' TextWrapping='WrapWholeWords' /> </Border> </DataTemplate> </controls:RecyclingElementFactory> </Grid.Resources> <ScrollViewer x:Name='Scroller' Width='400' Height='600' Background='Gray'> <controls:ItemsRepeater x:Name='ItemsRepeater' ElementFactory='{StaticResource ElementFactory}' Layout='{StaticResource VerticalStackLayout}' HorizontalCacheLength='0' VerticalCacheLength='0' /> </ScrollViewer> </Grid>")); var elementFactory = (RecyclingElementFactory)root.Resources["ElementFactory"]; scroller = (ScrollViewer)root.FindName("Scroller"); repeater = (ItemsRepeater)root.FindName("ItemsRepeater"); var items = Enumerable.Range(0, 400).Select(i => string.Format("{0}: {1}", i, lorem.Substring(0, 250))); repeater.ItemsSource = items; scroller.ViewChanged += (o, e) => { Log.Comment("ViewChanged: " + scroller.VerticalOffset); viewChangedOffsets.Add(scroller.VerticalOffset); if (!e.IsIntermediate) { viewChangeCompletedEvent.Set(); } }; scroller.EffectiveViewportChanged += (o, args) => { effectiveViewChangeCompletedEvent.Set(); }; Content = root; root.Loaded += delegate { rootLoadedEvent.Set(); }; }); Verify.IsTrue(rootLoadedEvent.WaitOne(DefaultWaitTimeInMS)); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { repeater.GetOrCreateElement(100).StartBringIntoView(); repeater.UpdateLayout(); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); IdleSynchronizer.Wait(); Verify.AreEqual(1, viewChangedOffsets.Count); viewChangedOffsets.Clear(); ValidateRealizedRange(repeater, 99, 106); RunOnUIThread.Execute(() => { Log.Comment("Scroll into view item 105 (already realized) w/ animation."); repeater.TryGetElement(105).StartBringIntoView(new BringIntoViewOptions { VerticalAlignmentRatio = 0.5, AnimationDesired = true }); repeater.UpdateLayout(); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); IdleSynchronizer.Wait(); Verify.IsLessThanOrEqual(1, viewChangedOffsets.Count); viewChangedOffsets.Clear(); ValidateRealizedRange(repeater, 99, 106); RunOnUIThread.Execute(() => { Log.Comment("Scroll item 0 to the top w/ animation and 0.5 vertical alignment."); repeater.GetOrCreateElement(0).StartBringIntoView(new BringIntoViewOptions { VerticalAlignmentRatio = 0.5, AnimationDesired = true }); repeater.UpdateLayout(); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); IdleSynchronizer.Wait(); viewChangedOffsets.Clear(); ValidateRealizedRange(repeater, 0, 6); RunOnUIThread.Execute(() => { // You can't align the first group in the middle obviously. Verify.AreEqual(0, scroller.VerticalOffset); Log.Comment("Scroll to item 20."); repeater.GetOrCreateElement(20).StartBringIntoView(new BringIntoViewOptions { VerticalAlignmentRatio = 0.0 }); repeater.UpdateLayout(); }); Verify.IsTrue(viewChangeCompletedEvent.WaitOne(DefaultWaitTimeInMS)); IdleSynchronizer.Wait(); ValidateRealizedRange(repeater, 19, 26); }
public void VerifyDefaultsAndBasicSetting() { NavigationView navView = null; Rectangle footer = null; TextBlock header = null; Setter styleSetter = null; Style hamburgerStyle = null; RunOnUIThread.Execute(() => { footer = new Rectangle(); footer.Height = 40; header = new TextBlock(); header.Text = "Header"; styleSetter = new Setter(); styleSetter.Property = FrameworkElement.MinHeightProperty; styleSetter.Value = "80"; hamburgerStyle = new Style(); navView = new NavigationView(); // Verify Defaults Verify.IsTrue(navView.IsPaneOpen); Verify.AreEqual(641, navView.CompactModeThresholdWidth); Verify.AreEqual(1008, navView.ExpandedModeThresholdWidth); Verify.IsNull(navView.PaneFooter); Verify.IsNull(navView.Header); Verify.IsTrue(navView.IsSettingsVisible); Verify.IsTrue(navView.IsPaneToggleButtonVisible); Verify.IsTrue(navView.IsTitleBarAutoPaddingEnabled); Verify.IsTrue(navView.AlwaysShowHeader); Verify.AreEqual(48, navView.CompactPaneLength); Verify.AreEqual(320, navView.OpenPaneLength); Verify.IsNull(navView.PaneToggleButtonStyle); Verify.AreEqual(0, navView.MenuItems.Count); Verify.AreEqual(NavigationViewDisplayMode.Minimal, navView.DisplayMode); Verify.AreEqual("", navView.PaneTitle); Verify.IsFalse(navView.IsBackEnabled); Verify.AreEqual(NavigationViewBackButtonVisible.Auto, navView.IsBackButtonVisible); // Verify basic setters navView.IsPaneOpen = true; navView.CompactModeThresholdWidth = 500; navView.ExpandedModeThresholdWidth = 1000; navView.PaneFooter = footer; navView.Header = header; navView.IsSettingsVisible = false; navView.IsPaneToggleButtonVisible = false; navView.IsTitleBarAutoPaddingEnabled = false; navView.AlwaysShowHeader = false; navView.CompactPaneLength = 40; navView.OpenPaneLength = 300; navView.PaneToggleButtonStyle = hamburgerStyle; navView.PaneTitle = "ChangedTitle"; navView.IsBackEnabled = true; navView.IsBackButtonVisible = NavigationViewBackButtonVisible.Visible; // TODO(test adding a MenuItem programmatically) }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.IsTrue(navView.IsPaneOpen); Verify.AreEqual(500, navView.CompactModeThresholdWidth); Verify.AreEqual(1000, navView.ExpandedModeThresholdWidth); Verify.AreEqual(footer, navView.PaneFooter); Verify.AreEqual(header, navView.Header); Verify.IsFalse(navView.IsSettingsVisible); Verify.IsFalse(navView.IsPaneToggleButtonVisible); Verify.IsFalse(navView.IsTitleBarAutoPaddingEnabled); Verify.IsFalse(navView.AlwaysShowHeader); Verify.AreEqual(40, navView.CompactPaneLength); Verify.AreEqual(300, navView.OpenPaneLength); Verify.AreEqual(hamburgerStyle, navView.PaneToggleButtonStyle); Verify.AreEqual("ChangedTitle", navView.PaneTitle); Verify.IsTrue(navView.IsBackEnabled); Verify.AreEqual(NavigationViewBackButtonVisible.Visible, navView.IsBackButtonVisible); // Verify nullable values navView.PaneFooter = null; navView.Header = null; navView.PaneToggleButtonStyle = null; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.IsNull(navView.PaneFooter); Verify.IsNull(navView.Header); Verify.IsNull(navView.PaneToggleButtonStyle); }); }
public void ValidateBasicScrollViewerScenario() { var realizationRects = new List <Rect>(); ScrollViewer scrollViewer = null; RunOnUIThread.Execute(() => { var repeater = new ItemsRepeater() { Layout = GetMonitoringLayout(new Size(500, 600), realizationRects), HorizontalCacheLength = 0.0, VerticalCacheLength = 0.0 }; scrollViewer = new ScrollViewer { Content = repeater, Width = 200, Height = 300, HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden, VerticalScrollBarVisibility = ScrollBarVisibility.Hidden, }; Content = scrollViewer; Content.UpdateLayout(); // First layout pass will invalidate measure during the first arrange // so that we can get a viewport during the second measure/arrange pass. Verify.AreEqual(2, realizationRects.Count); Verify.AreEqual(new Rect(0, 0, 0, 0), realizationRects[0]); Verify.AreEqual(new Rect(0, 0, 200, 300), realizationRects[1]); realizationRects.Clear(); scrollViewer.ChangeView(null, 100.0, 1.0f, disableAnimation: true); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(0, 100, 200, 300), realizationRects.Last()); realizationRects.Clear(); // Max viewport offset is (300, 400). Horizontal viewport offset // is expected to get coerced from 400 to 300. scrollViewer.ChangeView(400, 100.0, 1.0f, disableAnimation: true); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(300, 100, 200, 300), realizationRects.Last()); realizationRects.Clear(); scrollViewer.ChangeView(null, null, 2.0f, disableAnimation: true); }); IdleSynchronizer.Wait(); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(150, 50, 100, 150), realizationRects.Last()); realizationRects.Clear(); }); }
private NavigationView SetupNavigationViewScrolling(NavigationViewPaneDisplayMode paneDisplayMode = NavigationViewPaneDisplayMode.Auto) { NavigationView navView = null; RunOnUIThread.Execute(() => { navView = new NavigationView(); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #1", Icon = new SymbolIcon(Symbol.Undo) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #2", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItemHeader() { Content = "Item #3" }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #4", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #5", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItemSeparator()); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #7", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #8", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #9", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #10", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItemHeader() { Content = "Item #11" }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #12", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #13", Icon = new SymbolIcon(Symbol.Cut) }); navView.MenuItems.Add(new NavigationViewItemSeparator()); navView.MenuItems.Add(new NavigationViewItem() { Content = "Item #15", Icon = new SymbolIcon(Symbol.Cut) }); navView.IsBackButtonVisible = NavigationViewBackButtonVisible.Visible; navView.IsSettingsVisible = true; navView.PaneDisplayMode = paneDisplayMode; navView.OpenPaneLength = 120.0; navView.ExpandedModeThresholdWidth = 600.0; navView.CompactModeThresholdWidth = 400.0; navView.Width = 800.0; navView.Height = 200.0; navView.Content = "This test should have enough NavigationViewItems to scroll."; Content = navView; //Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TryEnterFullScreenMode(); Application.Current.MainWindow.WindowState = WindowState.Maximized; }); IdleSynchronizer.Wait(); return(navView); }
public void VerifyNumberBoxCornerRadius() { /* * if (PlatformConfiguration.IsOSVersionLessThan(OSVersion.Redstone5)) * { * Log.Warning("NumberBox CornerRadius property is not available pre-rs5"); * return; * } */ var numberBox = SetupNumberBox(); RepeatButton spinButtonDown = null; TextBox textBox = null; RunOnUIThread.Execute(() => { // first test: Uniform corner radius of '2' with no spin buttons shown numberBox.SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Hidden; numberBox.CornerRadius = new CornerRadius(2); Content.UpdateLayout(); textBox = TestUtilities.FindDescendents <TextBox>(numberBox).Where(e => e.Name == "InputBox").Single(); Verify.AreEqual(new CornerRadius(2, 2, 2, 2), textBox.GetCornerRadius()); // second test: Uniform corner radius of '2' with spin buttons in inline mode (T-rule applies now) numberBox.SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Inline; Content.UpdateLayout(); spinButtonDown = TestUtilities.FindDescendents <RepeatButton>(numberBox).Where(e => e.Name == "DownSpinButton").Single(); Verify.AreEqual(new CornerRadius(2, 0, 0, 2), textBox.GetCornerRadius()); Verify.AreEqual(new CornerRadius(0, 2, 2, 0), spinButtonDown.GetCornerRadius()); // third test: Set uniform corner radius to '4' with spin buttons in inline mode numberBox.CornerRadius = new CornerRadius(4); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { // This check makes sure that updating the CornerRadius values of the numberbox in inline mode // does not break the T-rule. Verify.AreEqual(new CornerRadius(4, 0, 0, 4), textBox.GetCornerRadius()); Verify.AreEqual(new CornerRadius(0, 4, 4, 0), spinButtonDown.GetCornerRadius()); // fourth test: Update the spin button placement mode to 'compact' and verify that all corners // of the textbox are now rounded again numberBox.SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact; Content.UpdateLayout(); Verify.AreEqual(new CornerRadius(4), textBox.GetCornerRadius()); // fifth test: Check corner radius of 0 in compact mode. numberBox.CornerRadius = new CornerRadius(0); Content.UpdateLayout(); Verify.AreEqual(new CornerRadius(0), textBox.GetCornerRadius()); }); }
public void BasicMargin() { if (!PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone2)) { Log.Comment("Skipping test on RS1."); return; } const double c_Margin = 50.0; Scroller scroller = null; Rectangle rectangleScrollerContent = null; AutoResetEvent scrollerLoadedEvent = new AutoResetEvent(false); RunOnUIThread.Execute(() => { rectangleScrollerContent = new Rectangle(); scroller = new Scroller(); SetupDefaultUI(scroller, rectangleScrollerContent, scrollerLoadedEvent); }); WaitForEvent("Waiting for Loaded event", scrollerLoadedEvent); RunOnUIThread.Execute(() => { Log.Comment("Adding positive Margin to Scroller.Content"); rectangleScrollerContent.Margin = new Thickness(c_Margin); }); // Try to jump beyond maximum offsets ChangeOffsets( scroller, c_defaultUIScrollerContentWidth + 2 * c_Margin - c_defaultUIScrollerWidth + 10.0, c_defaultUIScrollerContentHeight + 2 * c_Margin - c_defaultUIScrollerHeight + 10.0, ScrollerViewKind.Absolute, ScrollerViewChangeKind.DisableAnimation, ScrollerViewChangeSnapPointRespect.IgnoreSnapPoints, true /*hookViewChanged*/, c_defaultUIScrollerContentWidth + 2 * c_Margin - c_defaultUIScrollerWidth, c_defaultUIScrollerContentHeight + 2 * c_Margin - c_defaultUIScrollerHeight); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Adding negative Margin to Scroller.Content"); rectangleScrollerContent.Margin = new Thickness(-c_Margin); }); // Try to jump beyond maximum offsets ChangeOffsets( scroller, c_defaultUIScrollerContentWidth - 2 * c_Margin - c_defaultUIScrollerWidth + 10.0, c_defaultUIScrollerContentHeight - 2 * c_Margin - c_defaultUIScrollerHeight + 10.0, ScrollerViewKind.Absolute, ScrollerViewChangeKind.DisableAnimation, ScrollerViewChangeSnapPointRespect.IgnoreSnapPoints, false /*hookViewChanged*/, c_defaultUIScrollerContentWidth - 2 * c_Margin - c_defaultUIScrollerWidth, c_defaultUIScrollerContentHeight - 2 * c_Margin - c_defaultUIScrollerHeight); }
public void VerifyCustomItemTemplate() { RadioButtons radioButtons = null; RadioButtons radioButtons2 = null; RunOnUIThread.Execute(() => { radioButtons = new RadioButtons(); radioButtons.ItemsSource = new List <string>() { "Option 1", "Option 2" }; // Set a custom ItemTemplate to be wrapped in a RadioButton. var itemTemplate = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <TextBlock Text = '{Binding}'/> </DataTemplate>"); radioButtons.ItemTemplate = itemTemplate; radioButtons2 = new RadioButtons(); radioButtons2.ItemsSource = new List <string>() { "Option 1", "Option 2" }; // Set a custom ItemTemplate which is already a RadioButton. No wrapping should be performed. var itemTemplate2 = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <RadioButton Foreground='Blue'> <TextBlock Text = '{Binding}'/> </RadioButton> </DataTemplate>"); radioButtons2.ItemTemplate = itemTemplate2; var stackPanel = new StackPanel(); stackPanel.Children.Add(radioButtons); stackPanel.Children.Add(radioButtons2); Content = stackPanel; Content.UpdateLayout(); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var radioButton1 = radioButtons.ContainerFromIndex(0) as RadioButton; var radioButton2 = radioButtons2.ContainerFromIndex(0) as RadioButton; Verify.IsNotNull(radioButton1, "Our custom ItemTemplate should have been wrapped in a RadioButton."); Verify.IsNotNull(radioButton2, "Our custom ItemTemplate should have been wrapped in a RadioButton."); bool testCondition = !(radioButton1.Foreground is SolidColorBrush brush && brush.Color == Colors.Blue); Verify.IsTrue(testCondition, "Default foreground color of the RadioButton should not have been [blue]."); testCondition = radioButton2.Foreground is SolidColorBrush brush2 && brush2.Color == Colors.Blue; Verify.IsTrue(testCondition, "The foreground color of the RadioButton should have been [blue]."); }); }
public async Task ValidateTabNavigation() { if (!PlatformConfiguration.IsOsVersionGreaterThan(OSVersion.Redstone2)) { Log.Warning("Test is disabled on anything lower than RS3 because the GetChildrenInTabFocusOrder API is not available on previous versions."); return; } ItemsRepeater repeater = null; ScrollViewer scrollViewer = null; var data = new ObservableCollection <string>(Enumerable.Range(0, 50).Select(i => "Item #" + i)); var viewChangedEvent = new AutoResetEvent(false); await RunOnUIThread.ExecuteAsync(() => { var itemTemplate = (DataTemplate)XamlReader.Load( @"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'> <Button Content='{Binding}' Height='100' /> </DataTemplate>"); var elementFactory = new RecyclingElementFactory() { RecyclePool = new RecyclePool(), Templates = { { "itemTemplate", itemTemplate }, } }; Content = CreateAndInitializeRepeater ( data, new StackLayout(), elementFactory, ref repeater, ref scrollViewer ); scrollViewer.ViewChanged += (s, e) => { if (!e.IsIntermediate) { viewChangedEvent.Set(); } }; repeater.TabFocusNavigation = KeyboardNavigationMode.Local; Content.UpdateLayout(); }); await TestServices.WindowHelper.WaitForIdle(); await RunOnUIThread.ExecuteAsync(() => { ValidateTabNavigationOrder(repeater); }); IdleSynchronizer.Wait(); await RunOnUIThread.ExecuteAsync(() => { // Move window - disconnected scrollViewer.ChangeView(null, 2000, null, true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTimeInMS), "Waiting for final ViewChanged event."); IdleSynchronizer.Wait(); await RunOnUIThread.ExecuteAsync(() => { ValidateTabNavigationOrder(repeater); // Delete a couple of elements and validate we // ignore unrealized elements. // First visible element is expected to be index 20. while (data.Count > 21) { data.RemoveAt(21); } repeater.UpdateLayout(); }); await TestServices.WindowHelper.WaitForIdle(); await RunOnUIThread.ExecuteAsync(() => { ValidateTabNavigationOrder(repeater); }); }
private void NestedRepeaterWithDataTemplateScenario(bool disableAnimation) { if (!disableAnimation && PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone5)) { Log.Warning("This test is showing consistent issues with not scrolling enough on RS5 and 19H1 when animations are enabled, tracked by microsoft-ui-xaml#779"); return; } // Example of how to include debug tracing in an ApiTests.ItemsRepeater test's output. // using (PrivateLoggingHelper privateLoggingHelper = new PrivateLoggingHelper("Repeater")) // { ItemsRepeater rootRepeater = null; ScrollViewer scrollViewer = null; ManualResetEvent viewChanged = new ManualResetEvent(false); RunOnUIThread.Execute(() => { var anchorProvider = (ItemsRepeaterScrollHost)XamlReader.Load( @"<controls:ItemsRepeaterScrollHost Width='400' Height='600' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:controls='using:Microsoft.UI.Xaml.Controls'> <controls:ItemsRepeaterScrollHost.Resources> <DataTemplate x:Key='ItemTemplate' > <TextBlock Text='{Binding}' /> </DataTemplate> <DataTemplate x:Key='GroupTemplate'> <StackPanel> <TextBlock Text='{Binding}' /> <controls:ItemsRepeater ItemTemplate='{StaticResource ItemTemplate}' ItemsSource='{Binding}' VerticalCacheLength='0'/> </StackPanel> </DataTemplate> </controls:ItemsRepeaterScrollHost.Resources> <ScrollViewer x:Name='scrollviewer'> <controls:ItemsRepeater x:Name='rootRepeater' ItemTemplate='{StaticResource GroupTemplate}' VerticalCacheLength='0' /> </ScrollViewer> </controls:ItemsRepeaterScrollHost>"); rootRepeater = (ItemsRepeater)anchorProvider.FindName("rootRepeater"); rootRepeater.SizeChanged += (sender, args) => { Log.Comment($"SizeChanged: Size=({rootRepeater.ActualWidth} x {rootRepeater.ActualHeight})"); }; scrollViewer = (ScrollViewer)anchorProvider.FindName("scrollviewer"); scrollViewer.ViewChanging += (sender, args) => { Log.Comment($"ViewChanging: Next VerticalOffset={args.NextView.VerticalOffset}, Final VerticalOffset={args.FinalView.VerticalOffset}"); }; scrollViewer.ViewChanged += (sender, args) => { Log.Comment($"ViewChanged: VerticalOffset={scrollViewer.VerticalOffset}, IsIntermediate={args.IsIntermediate}"); if (!args.IsIntermediate) { viewChanged.Set(); } }; var itemsSource = new ObservableCollection <ObservableCollection <int> >(); for (int i = 0; i < 100; i++) { itemsSource.Add(new ObservableCollection <int>(Enumerable.Range(0, 5))); } ; rootRepeater.ItemsSource = itemsSource; Content = anchorProvider; }); // scroll down several times to cause recycling of elements for (int i = 1; i < 10; i++) { IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment($"Size=({rootRepeater.ActualWidth} x {rootRepeater.ActualHeight})"); Log.Comment($"ChangeView(VerticalOffset={i * 200})"); scrollViewer.ChangeView(null, i * 200, null, disableAnimation); }); Log.Comment("Waiting for view change completion..."); Verify.IsTrue(viewChanged.WaitOne(DefaultWaitTimeInMS)); viewChanged.Reset(); Log.Comment("View change completed"); RunOnUIThread.Execute(() => { Verify.AreEqual(i * 200, scrollViewer.VerticalOffset); }); } // } }