From 138ea74b88f64e2977482583b9e4042d68567b24 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Nov 2019 19:32:09 +0000 Subject: [PATCH 1/9] Add code to show desired syntax. --- samples/ControlCatalog/App.xaml | 5 +++++ samples/ControlCatalog/App.xaml.cs | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index e40509dfda..813a043b01 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -17,4 +17,9 @@ + + + + + diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 958729e2e8..b713c3dfd6 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -1,18 +1,32 @@ using System; +using System.Reactive; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using ReactiveUI; namespace ControlCatalog { public class App : Application { + public App() + { + DataContext = this; + + AboutCommand = ReactiveCommand.Create(() => + { + + }); + } + public override void Initialize() { AvaloniaXamlLoader.Load(this); } + public ReactiveCommand AboutCommand { get; } + public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) From 6a74ab560c96078aa15e268900df342c47d6f50d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 25 Nov 2019 10:05:45 +0100 Subject: [PATCH 2/9] Added IDataContextProvider. So that non-`IStyledElement`s can take part in binding. Apply the interface to `Application`. --- src/Avalonia.Controls/Application.cs | 22 +++++++++++++++++++- src/Avalonia.Styling/IDataContextProvider.cs | 13 ++++++++++++ src/Avalonia.Styling/IStyledElement.cs | 8 ++----- src/Avalonia.Styling/StyledElement.cs | 2 +- src/Markup/Avalonia.Markup/Data/Binding.cs | 4 ++-- 5 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 src/Avalonia.Styling/IDataContextProvider.cs diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 59c6c47ed9..9df92a49bc 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -32,7 +32,7 @@ namespace Avalonia /// method. /// - Tracks the lifetime of the application. /// - public class Application : AvaloniaObject, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode + public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode { /// /// The application-global data templates. @@ -45,6 +45,13 @@ namespace Avalonia private Styles _styles; private IResourceDictionary _resources; + /// + /// Defines the property. + /// + public static readonly StyledProperty DataContextProperty = + AvaloniaProperty.Register( + nameof(DataContext)); + /// public event EventHandler ResourcesChanged; @@ -56,6 +63,19 @@ namespace Avalonia Name = "Avalonia Application"; } + /// + /// Gets or sets the Applications's data context. + /// + /// + /// The data context property specifies the default object that will + /// be used for data binding. + /// + public object DataContext + { + get { return GetValue(DataContextProperty); } + set { SetValue(DataContextProperty, value); } + } + /// /// Gets the current instance of the class. /// diff --git a/src/Avalonia.Styling/IDataContextProvider.cs b/src/Avalonia.Styling/IDataContextProvider.cs new file mode 100644 index 0000000000..31639c5784 --- /dev/null +++ b/src/Avalonia.Styling/IDataContextProvider.cs @@ -0,0 +1,13 @@ +namespace Avalonia +{ + /// + /// Defines an element with a data context that can be used for binding. + /// + public interface IDataContextProvider : IAvaloniaObject + { + /// + /// Gets or sets the element's data context. + /// + object DataContext { get; set; } + } +} diff --git a/src/Avalonia.Styling/IStyledElement.cs b/src/Avalonia.Styling/IStyledElement.cs index bcf1898c4c..d4d0f179c3 100644 --- a/src/Avalonia.Styling/IStyledElement.cs +++ b/src/Avalonia.Styling/IStyledElement.cs @@ -10,7 +10,8 @@ namespace Avalonia IStyleHost, ILogical, IResourceProvider, - IResourceNode + IResourceNode, + IDataContextProvider { /// /// Occurs when the control has finished initialization. @@ -27,11 +28,6 @@ namespace Avalonia /// new Classes Classes { get; set; } - /// - /// Gets or sets the control's data context. - /// - object DataContext { get; set; } - /// /// Gets the control's logical parent. /// diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs index de8093c048..cf3c4dc855 100644 --- a/src/Avalonia.Styling/StyledElement.cs +++ b/src/Avalonia.Styling/StyledElement.cs @@ -24,7 +24,7 @@ namespace Avalonia /// - Implements to form part of a logical tree. /// - A collection of class strings for custom styling. /// - public class StyledElement : Animatable, IStyledElement, ISetLogicalParent, ISetInheritanceParent + public class StyledElement : Animatable, IDataContextProvider, IStyledElement, ISetLogicalParent, ISetInheritanceParent { /// /// Defines the property. diff --git a/src/Markup/Avalonia.Markup/Data/Binding.cs b/src/Markup/Avalonia.Markup/Data/Binding.cs index 61d0f7c83b..b4545f792e 100644 --- a/src/Markup/Avalonia.Markup/Data/Binding.cs +++ b/src/Markup/Avalonia.Markup/Data/Binding.cs @@ -231,9 +231,9 @@ namespace Avalonia.Data { Contract.Requires(target != null); - if (!(target is IStyledElement)) + if (!(target is IDataContextProvider)) { - target = anchor as IStyledElement; + target = anchor as IDataContextProvider; if (target == null) { From 7b11d7674aecbd31e8c15bee1c2715ffd798105e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 09:28:42 +0000 Subject: [PATCH 3/9] implement IDataContextProvider on NativeMenuItem --- src/Avalonia.Controls/NativeMenuItemBase.cs | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs index 47eb86cdc3..fa2ecd609a 100644 --- a/src/Avalonia.Controls/NativeMenuItemBase.cs +++ b/src/Avalonia.Controls/NativeMenuItemBase.cs @@ -2,7 +2,7 @@ namespace Avalonia.Controls { - public class NativeMenuItemBase : AvaloniaObject + public class NativeMenuItemBase : AvaloniaObject, IDataContextProvider { private NativeMenu _parent; @@ -11,6 +11,7 @@ namespace Avalonia.Controls } + public static readonly DirectProperty ParentProperty = AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v); @@ -19,5 +20,26 @@ namespace Avalonia.Controls get => _parent; set => SetAndRaise(ParentProperty, ref _parent, value); } + + /// + /// Defines the property. + /// + public static readonly StyledProperty DataContextProperty = + AvaloniaProperty.Register( + nameof(DataContext)); + + /// + /// Gets or sets the controls's data context. + /// + /// + /// The data context property + /// specifies the default object that will + /// be used for data binding. + /// + public object DataContext + { + get { return GetValue(DataContextProperty); } + set { SetValue(DataContextProperty, value); } + } } } From 7eea7f65c65fca0b7f4e35b3b8a518e31afc687b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:07:18 +0000 Subject: [PATCH 4/9] dont implement datacontext on menuitems --- src/Avalonia.Controls/NativeMenuItemBase.cs | 24 +-------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs index fa2ecd609a..47eb86cdc3 100644 --- a/src/Avalonia.Controls/NativeMenuItemBase.cs +++ b/src/Avalonia.Controls/NativeMenuItemBase.cs @@ -2,7 +2,7 @@ namespace Avalonia.Controls { - public class NativeMenuItemBase : AvaloniaObject, IDataContextProvider + public class NativeMenuItemBase : AvaloniaObject { private NativeMenu _parent; @@ -11,7 +11,6 @@ namespace Avalonia.Controls } - public static readonly DirectProperty ParentProperty = AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v); @@ -20,26 +19,5 @@ namespace Avalonia.Controls get => _parent; set => SetAndRaise(ParentProperty, ref _parent, value); } - - /// - /// Defines the property. - /// - public static readonly StyledProperty DataContextProperty = - AvaloniaProperty.Register( - nameof(DataContext)); - - /// - /// Gets or sets the controls's data context. - /// - /// - /// The data context property - /// specifies the default object that will - /// be used for data binding. - /// - public object DataContext - { - get { return GetValue(DataContextProperty); } - set { SetValue(DataContextProperty, value); } - } } } From eb6f3e620d802b495f0120204cc4b9c3590a9a4a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:07:45 +0000 Subject: [PATCH 5/9] GetDefaultAnchor will looks for IDataContextProviders --- .../MarkupExtensions/BindingExtension.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs index a466714136..7532e01f55 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -52,6 +52,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions // the context. object anchor = context.GetFirstParent(); + if(anchor is null) + { + anchor = context.GetFirstParent(); + } + // If a control was not found, then try to find the highest-level style as the XAML // file could be a XAML file containing only styles. return anchor ?? From 2ffb1af3bc0fbbcd6f666e4cf62d63111e9f03ef Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 10:08:55 +0000 Subject: [PATCH 6/9] add comment --- .../Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs index 7532e01f55..20f68df820 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -54,6 +54,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions if(anchor is null) { + // Try to find IDataContextProvider, this was added to allow us to find + // a datacontext for Application class when using NativeMenuItems. anchor = context.GetFirstParent(); } From 055115415c4aaad19f755aa525e778014444ec67 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:11:29 +0000 Subject: [PATCH 7/9] Application class uses AddOwner instead of making its own version of datacontext property. --- src/Avalonia.Controls/Application.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 9df92a49bc..9158ac7038 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -49,8 +49,7 @@ namespace Avalonia /// Defines the property. /// public static readonly StyledProperty DataContextProperty = - AvaloniaProperty.Register( - nameof(DataContext)); + StyledElement.DataContextProperty.AddOwner(); /// public event EventHandler ResourcesChanged; From c37562971734e5bbad55055ec47410235c48e3ad Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:31:12 +0000 Subject: [PATCH 8/9] restore app.xaml /cs --- samples/ControlCatalog/App.xaml | 5 ----- samples/ControlCatalog/App.xaml.cs | 6 ------ 2 files changed, 11 deletions(-) diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index 813a043b01..e40509dfda 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -17,9 +17,4 @@ - - - - - diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index b713c3dfd6..ea5ae0a75b 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -12,12 +12,6 @@ namespace ControlCatalog { public App() { - DataContext = this; - - AboutCommand = ReactiveCommand.Create(() => - { - - }); } public override void Initialize() From 79527e6ab9e195437fb533e1e12f2ab435682e45 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 25 Nov 2019 12:35:15 +0000 Subject: [PATCH 9/9] restore app.xaml.cs --- samples/ControlCatalog/App.xaml.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index ea5ae0a75b..52a9591c94 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -1,33 +1,23 @@ -using System; -using System.Reactive; using Avalonia; -using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; -using ReactiveUI; namespace ControlCatalog { public class App : Application { - public App() - { - } - public override void Initialize() { AvaloniaXamlLoader.Load(this); } - public ReactiveCommand AboutCommand { get; } - public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) desktopLifetime.MainWindow = new MainWindow(); else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime) singleViewLifetime.MainView = new MainView(); - + base.OnFrameworkInitializationCompleted(); } }