using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Reactive.Subjects; using System.Text; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Controls.Presenters; using Avalonia.Data.Core; using Avalonia.Markup.Data; using Avalonia.UnitTests; using XamlX; using Xunit; namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions { public class CompiledBindingExtensionTests { [Fact] public void ResolvesClrPropertyBasedOnDataContextType() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { StringProperty = "foobar" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ResolvesPathPassedByProperty() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { StringProperty = "foobar" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ResolvesStreamTaskBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { TaskProperty = Task.FromResult("foobar") }; window.DataContext = dataContext; Assert.Equal(dataContext.TaskProperty.Result, textBlock.Text); } } [Fact] public void ResolvesStreamObservableBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); DelayedBinding.ApplyBindings(textBlock); var subject = new Subject(); var dataContext = new TestDataContext { ObservableProperty = subject }; window.DataContext = dataContext; subject.OnNext("foobar"); Assert.Equal("foobar", textBlock.Text); } } [Fact] public void ResolvesIndexerBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { ListProperty = { "A", "B", "C", "D", "E" } }; window.DataContext = dataContext; Assert.Equal(dataContext.ListProperty[3], textBlock.Text); } } [Fact] public void ResolvesArrayIndexerBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { ArrayProperty = new[] { "A", "B", "C", "D", "E" } }; window.DataContext = dataContext; Assert.Equal(dataContext.ArrayProperty[3], textBlock.Text); } } [Fact] public void ResolvesObservableIndexerBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { ObservableCollectionProperty = { "A", "B", "C", "D", "E" } }; window.DataContext = dataContext; Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text); dataContext.ObservableCollectionProperty[3] = "New Value"; Assert.Equal(dataContext.ObservableCollectionProperty[3], textBlock.Text); } } [Fact] public void InfersCompiledBindingDataContextFromDataContextBinding() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); var dataContext = new TestDataContext { StringProperty = "A" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ResolvesNonIntegerIndexerBindingCorrectly() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext(); dataContext.NonIntegerIndexerProperty["Test"] = "Initial Value"; window.DataContext = dataContext; Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text); dataContext.NonIntegerIndexerProperty["Test"] = "New Value"; Assert.Equal(dataContext.NonIntegerIndexerProperty["Test"], textBlock.Text); } } [Fact] public void InfersDataTemplateTypeFromDataTypeProperty() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var target = window.FindControl("target"); var dataContext = new TestDataContext(); dataContext.StringProperty = "Initial Value"; window.DataContext = dataContext; window.ApplyTemplate(); target.ApplyTemplate(); ((ContentPresenter)target.Presenter).UpdateChild(); Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text); } } [Fact] public void ThrowsOnUninferrableLooseDataTemplateNoDataTypeWithCompiledBindingPath() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); Assert.Throws(() => loader.Load(xaml)); } } [Fact] public void ThrowsOnUninferrableDataTypeFromNonCompiledDataContextBindingWithCompiledBindingPath() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); Assert.Throws(() => loader.Load(xaml)); } } [Fact] public void InfersDataTemplateTypeFromParentCollectionItemsType() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var target = window.FindControl("target"); var dataContext = new TestDataContext(); dataContext.ListProperty.Add("Test"); window.DataContext = dataContext; window.ApplyTemplate(); target.ApplyTemplate(); target.Presenter.ApplyTemplate(); Assert.Equal(dataContext.ListProperty[0], (string)((ContentPresenter)target.Presenter.Panel.Children[0]).Content); } } [Fact] public void ThrowsOnUninferrableDataTemplateInItemsControlWithoutItemsBinding() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); Assert.Throws(() => loader.Load(xaml)); } } [Fact] public void ResolvesElementNameBinding() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("text2"); var dataContext = new TestDataContext { StringProperty = "foobar" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ResolvesElementNameBindingFromLongForm() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("text2"); var dataContext = new TestDataContext { StringProperty = "foobar" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ResolvesRelativeSourceBindingLongForm() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var target = window.FindControl("text"); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); target.ApplyTemplate(); Assert.Equal("test", target.Text); } } [Fact] public void ResolvesSourceBindingLongForm() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var target = window.FindControl("text"); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); target.ApplyTemplate(); Assert.Equal("Test".Length.ToString(), target.Text); } } [Fact] public void CompilesBindingWhenRequested() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); var textBlock = window.FindControl("textBlock"); var dataContext = new TestDataContext { StringProperty = "foobar" }; window.DataContext = dataContext; Assert.Equal(dataContext.StringProperty, textBlock.Text); } } [Fact] public void ThrowsOnInvalidBindingPathOnCompiledBindingEnabledViaDirective() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); Assert.Throws(() => loader.Load(xaml)); } } [Fact] public void ThrowsOnInvalidCompileBindingsDirective() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var loader = new AvaloniaXamlLoader(); Assert.Throws(() => loader.Load(xaml)); } } } public class TestDataContext { public string StringProperty { get; set; } public Task TaskProperty { get; set; } public IObservable ObservableProperty { get; set; } public ObservableCollection ObservableCollectionProperty { get; set; } = new ObservableCollection(); public string[] ArrayProperty { get; set; } public List ListProperty { get; set; } = new List(); public NonIntegerIndexer NonIntegerIndexerProperty { get; set; } = new NonIntegerIndexer(); public class NonIntegerIndexer : NotifyingBase { private readonly Dictionary _storage = new Dictionary(); public string this[string key] { get { return _storage[key]; } set { _storage[key] = value; RaisePropertyChanged(CommonPropertyNames.IndexerName); } } } } }