Преглед на файлове

Merge pull request #3288 from AvaloniaUI/grokys/datacontextprovider

Add DataContext to Application so we can bind Application menu commands
Benedikt Stebner преди 6 години
родител
ревизия
7f1135257e

+ 1 - 3
samples/ControlCatalog/App.xaml.cs

@@ -1,6 +1,4 @@
-using System;
 using Avalonia;
-using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Markup.Xaml;
 
@@ -19,7 +17,7 @@ namespace ControlCatalog
                 desktopLifetime.MainWindow = new MainWindow();
             else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
                 singleViewLifetime.MainView = new MainView();
-            
+
             base.OnFrameworkInitializationCompleted();
         }
     }

+ 20 - 1
src/Avalonia.Controls/Application.cs

@@ -32,7 +32,7 @@ namespace Avalonia
     /// method.
     /// - Tracks the lifetime of the application.
     /// </remarks>
-    public class Application : AvaloniaObject, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode
+    public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IStyleRoot, IResourceNode
     {
         /// <summary>
         /// The application-global data templates.
@@ -45,6 +45,12 @@ namespace Avalonia
         private Styles _styles;
         private IResourceDictionary _resources;
 
+        /// <summary>
+        /// Defines the <see cref="DataContext"/> property.
+        /// </summary>
+        public static readonly StyledProperty<object> DataContextProperty =
+            StyledElement.DataContextProperty.AddOwner<Application>();
+
         /// <inheritdoc/>
         public event EventHandler<ResourcesChangedEventArgs> ResourcesChanged;
 
@@ -56,6 +62,19 @@ namespace Avalonia
             Name = "Avalonia Application";
         }
 
+        /// <summary>
+        /// Gets or sets the Applications's data context.
+        /// </summary>
+        /// <remarks>
+        /// The data context property specifies the default object that will
+        /// be used for data binding.
+        /// </remarks>
+        public object DataContext
+        {
+            get { return GetValue(DataContextProperty); }
+            set { SetValue(DataContextProperty, value); }
+        }
+
         /// <summary>
         /// Gets the current instance of the <see cref="Application"/> class.
         /// </summary>

+ 13 - 0
src/Avalonia.Styling/IDataContextProvider.cs

@@ -0,0 +1,13 @@
+namespace Avalonia
+{
+    /// <summary>
+    /// Defines an element with a data context that can be used for binding.
+    /// </summary>
+    public interface IDataContextProvider : IAvaloniaObject
+    {
+        /// <summary>
+        /// Gets or sets the element's data context.
+        /// </summary>
+        object DataContext { get; set; }
+    }
+}

+ 2 - 6
src/Avalonia.Styling/IStyledElement.cs

@@ -10,7 +10,8 @@ namespace Avalonia
         IStyleHost,
         ILogical,
         IResourceProvider,
-        IResourceNode
+        IResourceNode,
+        IDataContextProvider
     {
         /// <summary>
         /// Occurs when the control has finished initialization.
@@ -27,11 +28,6 @@ namespace Avalonia
         /// </summary>
         new Classes Classes { get; set; }
 
-        /// <summary>
-        /// Gets or sets the control's data context.
-        /// </summary>
-        object DataContext { get; set; }
-
         /// <summary>
         /// Gets the control's logical parent.
         /// </summary>

+ 1 - 1
src/Avalonia.Styling/StyledElement.cs

@@ -24,7 +24,7 @@ namespace Avalonia
     /// - Implements <see cref="ILogical"/> to form part of a logical tree.
     /// - A collection of class strings for custom styling.
     /// </summary>
-    public class StyledElement : Animatable, IStyledElement, ISetLogicalParent, ISetInheritanceParent
+    public class StyledElement : Animatable, IDataContextProvider, IStyledElement, ISetLogicalParent, ISetInheritanceParent
     {
         /// <summary>
         /// Defines the <see cref="DataContext"/> property.

+ 7 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs

@@ -52,6 +52,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
             // the context.
             object anchor = context.GetFirstParent<IControl>();
 
+            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<IDataContextProvider>();
+            }
+
             // 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 ??

+ 2 - 2
src/Markup/Avalonia.Markup/Data/Binding.cs

@@ -231,9 +231,9 @@ namespace Avalonia.Data
         {
             Contract.Requires<ArgumentNullException>(target != null);
 
-            if (!(target is IStyledElement))
+            if (!(target is IDataContextProvider))
             {
-                target = anchor as IStyledElement;
+                target = anchor as IDataContextProvider;
 
                 if (target == null)
                 {