| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Xml;
- using Avalonia.Controls;
- using Avalonia.Markup.Xaml.Styling;
- using Avalonia.Markup.Xaml.Templates;
- using Avalonia.Media;
- using Avalonia.Styling;
- using Avalonia.UnitTests;
- using Xunit;
- namespace Avalonia.Markup.Xaml.UnitTests.Xaml
- {
- public class StyleTests : XamlTestBase
- {
- static StyleTests()
- {
- GC.KeepAlive(typeof(ItemsRepeater));
- }
- [Fact]
- public void Color_Can_Be_Added_To_Style_Resources()
- {
- using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
- {
- var xaml = @"
- <UserControl xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <UserControl.Styles>
- <Style>
- <Style.Resources>
- <Color x:Key='color'>#ff506070</Color>
- </Style.Resources>
- </Style>
- </UserControl.Styles>
- </UserControl>";
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var color = (Color)((Style)userControl.Styles[0]).Resources["color"];
- Assert.Equal(0xff506070, color.ToUint32());
- }
- }
- [Fact]
- public void DataTemplate_Can_Be_Added_To_Style_Resources()
- {
- using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
- {
- var xaml = @"
- <UserControl xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <UserControl.Styles>
- <Style>
- <Style.Resources>
- <DataTemplate x:Key='dataTemplate'><TextBlock/></DataTemplate>
- </Style.Resources>
- </Style>
- </UserControl.Styles>
- </UserControl>";
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var dataTemplate = (DataTemplate)((Style)userControl.Styles[0]).Resources["dataTemplate"];
- Assert.NotNull(dataTemplate);
- }
- }
- [Fact]
- public void ControlTemplate_Can_Be_Added_To_Style_Resources()
- {
- using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
- {
- var xaml = @"
- <UserControl xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <UserControl.Styles>
- <Style>
- <Style.Resources>
- <ControlTemplate x:Key='controlTemplate' TargetType='{x:Type Button}'>
- <ContentPresenter Content='{TemplateBinding Content}'/>
- </ControlTemplate>
- </Style.Resources>
- </Style>
- </UserControl.Styles>
- </UserControl>";
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var controlTemplate = (ControlTemplate)((Style)userControl.Styles[0]).Resources["controlTemplate"];
- Assert.NotNull(controlTemplate);
- Assert.Equal(typeof(Button), controlTemplate.TargetType);
- }
- }
- [Fact]
- public void SolidColorBrush_Can_Be_Added_To_Style_Resources()
- {
- using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
- {
- var xaml = @"
- <UserControl xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <UserControl.Styles>
- <Style>
- <Style.Resources>
- <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
- </Style.Resources>
- </Style>
- </UserControl.Styles>
- </UserControl>";
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var brush = (ISolidColorBrush)((Style)userControl.Styles[0]).Resources["brush"];
- Assert.Equal(0xff506070, brush.Color.ToUint32());
- }
- }
- [Fact]
- public void Setter_Can_Contain_Template()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='ContentControl'>
- <Setter Property='Content'>
- <Template>
- <TextBlock>Hello World!</TextBlock>
- </Template>
- </Setter>
- </Style>
- </Window.Styles>
- <ContentControl Name='target'/>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var target = window.Find<ContentControl>("target");
- Assert.IsType<TextBlock>(target.Content);
- Assert.Equal("Hello World!", ((TextBlock)target.Content).Text);
- }
- }
- [Fact]
- public void Setter_Value_Is_Bound_Directly_If_The_Target_Type_Derives_From_ITemplate()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector=':is(Control)'>
- <Setter Property='FocusAdorner'>
- <FocusAdornerTemplate>
- <Rectangle Stroke='Black'
- StrokeThickness='1'
- StrokeDashArray='1,2'/>
- </FocusAdornerTemplate>
- </Setter>
- </Style>
- </Window.Styles>
- <TextBlock Name='target'/>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var target = window.Find<TextBlock>("target");
- Assert.NotNull(target.FocusAdorner);
- }
- }
- [Fact]
- public void Setter_Can_Set_Attached_Property()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
- xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
- <Window.Styles>
- <Style Selector='TextBlock'>
- <Setter Property='DockPanel.Dock' Value='Right'/>
- </Style>
- </Window.Styles>
- <TextBlock/>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var textBlock = (TextBlock)window.Content;
- window.ApplyTemplate();
- Assert.Equal(Dock.Right, DockPanel.GetDock(textBlock));
- }
- }
- [Fact(Skip = "The animation system currently needs to be able to set any property on any object")]
- public void Disallows_Setting_Non_Registered_Property()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
- xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml;assembly=Avalonia.Markup.Xaml.UnitTests'>
- <Window.Styles>
- <Style Selector='TextBlock'>
- <Setter Property='Button.IsDefault' Value='True'/>
- </Style>
- </Window.Styles>
- <TextBlock/>
- </Window>";
- var ex = Assert.Throws<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
- Assert.Equal(
- "Property 'Button.IsDefault' is not registered on 'Avalonia.Controls.TextBlock'.",
- ex.InnerException.Message);
- }
- }
- [Fact]
- public void Style_Can_Use_Not_Selector()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border:not(.foo)'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border Name='foo' Classes='foo bar'/>
- <Border Name='notFoo' Classes='bar'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var foo = window.FindControl<Border>("foo");
- var notFoo = window.FindControl<Border>("notFoo");
- Assert.Null(foo.Background);
- Assert.Equal(Colors.Red, ((ISolidColorBrush)notFoo.Background).Color);
- }
- }
- [Fact]
- public void Style_Can_Use_NthChild_Selector()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border.foo:nth-child(2n+1)'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border x:Name='b1' Classes='foo'/>
- <Border x:Name='b2' />
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var b1 = window.FindControl<Border>("b1");
- var b2 = window.FindControl<Border>("b2");
- Assert.Equal(Brushes.Red, b1.Background);
- Assert.Null(b2.Background);
- }
- }
- [Fact]
- public void Style_Can_Use_NthChild_Selector_After_Reorder()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border:nth-child(2n)'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel x:Name='parent'>
- <Border x:Name='b1' />
- <Border x:Name='b2' />
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var parent = window.FindControl<StackPanel>("parent");
- var b1 = window.FindControl<Border>("b1");
- var b2 = window.FindControl<Border>("b2");
- Assert.Null(b1.Background);
- Assert.Equal(Brushes.Red, b2.Background);
- parent.Children.Remove(b1);
- Assert.Null(b1.Background);
- Assert.Null(b2.Background);
- parent.Children.Add(b1);
- Assert.Equal(Brushes.Red, b1.Background);
- Assert.Null(b2.Background);
- }
- }
- [Fact]
- public void Style_Can_Use_NthLastChild_Selector_After_Reorder()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border:nth-last-child(2n)'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel x:Name='parent'>
- <Border x:Name='b1' />
- <Border x:Name='b2' />
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var parent = window.FindControl<StackPanel>("parent");
- var b1 = window.FindControl<Border>("b1");
- var b2 = window.FindControl<Border>("b2");
- Assert.Equal(Brushes.Red, b1.Background);
- Assert.Null(b2.Background);
- parent.Children.Remove(b1);
- Assert.Null(b1.Background);
- Assert.Null(b2.Background);
- parent.Children.Add(b1);
- Assert.Null(b1.Background);
- Assert.Equal(Brushes.Red, b2.Background);
- }
- }
- [Fact]
- public void Style_Can_Use_NthChild_Selector_With_ListBox()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='ListBoxItem:nth-child(2n)'>
- <Setter Property='Background' Value='{Binding}'/>
- </Style>
- </Window.Styles>
- <ListBox x:Name='list' />
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var collection = new ObservableCollection<IBrush>()
- {
- Brushes.Red, Brushes.Green, Brushes.Blue
- };
- var list = window.FindControl<ListBox>("list");
- list.Items = collection;
- window.Show();
- IEnumerable<IBrush> GetColors() => list.GetRealizedContainers().Cast<ListBoxItem>().Select(t => t.Background);
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Green, Brushes.Transparent }, GetColors());
- collection.Remove(Brushes.Green);
- window.LayoutManager.ExecuteLayoutPass();
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Blue }, GetColors());
- collection.Add(Brushes.Violet);
- collection.Add(Brushes.Black);
- window.LayoutManager.ExecuteLayoutPass();
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Blue, Brushes.Transparent, Brushes.Black }, GetColors());
- }
- }
- [Fact]
- public void Style_Can_Use_NthChild_Selector_With_ItemsRepeater()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='TextBlock'>
- <Setter Property='Foreground' Value='Transparent'/>
- </Style>
- <Style Selector='TextBlock:nth-child(2n)'>
- <Setter Property='Foreground' Value='{Binding}'/>
- </Style>
- </Window.Styles>
- <ItemsRepeater x:Name='list' />
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var collection = new ObservableCollection<IBrush>()
- {
- Brushes.Red, Brushes.Green, Brushes.Blue
- };
- var list = window.FindControl<ItemsRepeater>("list");
- list.Items = collection;
- window.Show();
- IEnumerable<IBrush> GetColors() => Enumerable.Range(0, list.ItemsSourceView.Count)
- .Select(t => (list.GetOrCreateElement(t) as TextBlock)!.Foreground);
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Green, Brushes.Transparent }, GetColors());
- collection.Remove(Brushes.Green);
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Blue }, GetColors().ToList());
- collection.Add(Brushes.Violet);
- collection.Add(Brushes.Black);
- Assert.Equal(new[] { Brushes.Transparent, Brushes.Blue, Brushes.Transparent, Brushes.Black }, GetColors());
- }
- }
- [Fact]
- public void Style_Can_Use_Or_Selector_1()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border.foo, Border.bar'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border Name='foo' Classes='foo'/>
- <Border Name='bar' Classes='bar'/>
- <Border Name='baz' Classes='baz'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var foo = window.FindControl<Border>("foo");
- var bar = window.FindControl<Border>("bar");
- var baz = window.FindControl<Border>("baz");
- Assert.Equal(Brushes.Red, foo.Background);
- Assert.Equal(Brushes.Red, bar.Background);
- Assert.Null(baz.Background);
- }
- }
- [Fact]
- public void Style_Can_Use_Or_Selector_2()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Button,Carousel,ListBox'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Button Name='button'/>
- <Carousel Name='carousel'/>
- <ListBox Name='listBox'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var button = window.FindControl<Button>("button");
- var carousel = window.FindControl<Carousel>("carousel");
- var listBox = window.FindControl<ListBox>("listBox");
- Assert.Equal(Brushes.Red, button.Background);
- Assert.Equal(Brushes.Red, carousel.Background);
- Assert.Equal(Brushes.Red, listBox.Background);
- }
- }
- [Fact]
- public void Transitions_Can_Be_Styled()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border'>
- <Setter Property='Transitions'>
- <Transitions>
- <DoubleTransition Property='Width' Duration='0:0:1'/>
- </Transitions>
- </Setter>
- </Style>
- <Style Selector='Border.foo'>
- <Setter Property='Transitions'>
- <Transitions>
- <DoubleTransition Property='Height' Duration='0:0:1'/>
- </Transitions>
- </Setter>
- </Style>
- </Window.Styles>
- <Border/>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var border = (Border)window.Content;
- Assert.Equal(1, border.Transitions.Count);
- Assert.Equal(Border.WidthProperty, border.Transitions[0].Property);
- border.Classes.Add("foo");
- Assert.Equal(1, border.Transitions.Count);
- Assert.Equal(Border.HeightProperty, border.Transitions[0].Property);
- border.Classes.Remove("foo");
- Assert.Equal(1, border.Transitions.Count);
- Assert.Equal(Border.WidthProperty, border.Transitions[0].Property);
- }
- }
- [Fact]
- public void Style_Can_Use_Class_Selector_With_Dash()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border.foo-bar'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border Name='foo' Classes='foo-bar'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var foo = window.FindControl<Border>("foo");
- Assert.Equal(Colors.Red, ((ISolidColorBrush)foo.Background).Color);
- }
- }
- [Fact]
- public void Style_Can_Use_Pseudolass_Selector_With_Dash()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border:foo-bar'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border Name='foo'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var foo = window.FindControl<Border>("foo");
- Assert.Null(foo.Background);
- ((IPseudoClasses)foo.Classes).Add(":foo-bar");
- Assert.Equal(Colors.Red, ((ISolidColorBrush)foo.Background).Color);
- }
- }
- [Fact]
- public void Can_Use_Nested_Styles()
- {
- using (UnitTestApplication.Start(TestServices.StyledWindow))
- {
- var xaml = @"
- <Window xmlns='https://github.com/avaloniaui'
- xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
- <Window.Styles>
- <Style Selector='Border'>
- <Style Selector='^.foo'>
- <Setter Property='Background' Value='Red'/>
- </Style>
- </Style>
- </Window.Styles>
- <StackPanel>
- <Border Name='foo'/>
- </StackPanel>
- </Window>";
- var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
- var foo = window.FindControl<Border>("foo");
- Assert.Null(foo.Background);
- foo.Classes.Add("foo");
- Assert.Equal(Colors.Red, ((ISolidColorBrush)foo.Background).Color);
- }
- }
- }
- }
|