浏览代码

WPF embedding improvements

Nikita Tsukanov 8 年之前
父节点
当前提交
3126901721

+ 11 - 0
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml

@@ -1,6 +1,7 @@
 <Window x:Class="WindowsInteropTest.EmbedToWpfDemo"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:av="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:local="clr-namespace:WindowsInteropTest"
@@ -15,6 +16,16 @@
                 <Calendar/>
             </StackPanel>
         </GroupBox>
+        <GroupBox Header="Avalonia button" DockPanel.Dock="Bottom">
+            <wpf:WpfAvaloniaHost >
+                <av:Button Content="Avalonia button"/>
+            </wpf:WpfAvaloniaHost>
+        </GroupBox>
+        <GroupBox Header="AvBtn" DockPanel.Dock="Right">
+            <wpf:WpfAvaloniaHost x:Name="RightBtn">
+                <av:Button Content="Avalonia button 2"/>
+            </wpf:WpfAvaloniaHost>
+        </GroupBox>
         <GroupBox Header="Avalonia">
             <wpf:WpfAvaloniaHost x:Name="Host"/>
         </GroupBox>

+ 5 - 0
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs

@@ -32,6 +32,11 @@ namespace WindowsInteropTest
             {
                 view.AttachDevTools();
             };
+            var btn = (Avalonia.Controls.Button) RightBtn.Content;
+            btn.Click += delegate
+            {
+                btn.Content += "!";
+            };
 
         }
     }

+ 1 - 1
src/Avalonia.Layout/Layoutable.cs

@@ -370,7 +370,7 @@ namespace Avalonia.Layout
         /// <summary>
         /// Invalidates the measurement of the control and queues a new layout pass.
         /// </summary>
-        public void InvalidateMeasure()
+        public virtual void InvalidateMeasure()
         {
             if (IsMeasureValid)
             {

+ 12 - 0
src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj

@@ -68,6 +68,10 @@
       <Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
       <Name>Avalonia.Controls</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
+      <Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
+      <Name>Avalonia.DotNetFrameworkRuntime</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj">
       <Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
       <Name>Avalonia.Input</Name>
@@ -92,6 +96,14 @@
       <Project>{fb05ac90-89ba-4f2f-a924-f37875fb547c}</Project>
       <Name>Avalonia.Cairo</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
+      <Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
+      <Name>Avalonia.Markup.Xaml</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
+      <Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
+      <Name>Avalonia.Markup</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Avalonia.Win32\Avalonia.Win32.csproj">
       <Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
       <Name>Avalonia.Win32</Name>

+ 29 - 6
src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs

@@ -1,29 +1,35 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Markup;
 using System.Windows.Media;
+using Avalonia.Markup.Xaml.Styling;
+using Avalonia.Platform;
+using Avalonia.Styling;
 
 namespace Avalonia.Win32.Interop.Wpf
 {
-    public class WpfAvaloniaHost : FrameworkElement, IDisposable
+    [ContentProperty("Content")]
+    public class WpfAvaloniaHost : FrameworkElement, IDisposable, IAddChild
     {
-        private WpfTopLevelImpl _impl = new WpfTopLevelImpl();
+        private WpfTopLevelImpl _impl;
         private readonly SynchronizationContext _sync;
         public WpfAvaloniaHost()
         {
             _sync = SynchronizationContext.Current;
+            _impl = new WpfTopLevelImpl();
             _impl.ControlRoot.Prepare();
             _impl.Visibility = Visibility.Visible;
             AddLogicalChild(_impl);
             AddVisualChild(_impl);
         }
-        
 
         public object Content
         {
@@ -47,9 +53,13 @@ namespace Avalonia.Win32.Interop.Wpf
             }
         }
 
-        protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint) 
-            => _impl.ControlRoot.MeasureBase(constraint.ToAvaloniaSize()).ToWpfSize();
-        
+        protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
+        {
+            _impl.InvalidateMeasure();
+            _impl.Measure(constraint);
+            return _impl.DesiredSize;
+        }
+
         protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
         {
             _impl.Arrange(new System.Windows.Rect(arrangeSize));
@@ -76,5 +86,18 @@ namespace Avalonia.Win32.Interop.Wpf
                 GC.SuppressFinalize(this);
             }
         }
+
+        void IAddChild.AddChild(object value)
+        {
+            if (Content == null)
+                Content = value;
+            else
+                throw new InvalidOperationException();
+        }
+
+        void IAddChild.AddText(string text)
+        {
+            //
+        }
     }
 }

+ 11 - 0
src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs

@@ -33,6 +33,15 @@ namespace Avalonia.Win32.Interop.Wpf
         public EmbeddableControlRoot ControlRoot { get; }
         internal ImageSource ImageSource { get; set; }
 
+        public class CustomControlRoot : EmbeddableControlRoot
+        {
+            public override void InvalidateMeasure()
+            {
+                base.InvalidateMeasure();
+                ((FrameworkElement)PlatformImpl)?.InvalidateMeasure();
+            }
+        }
+
         public WpfTopLevelImpl()
         {
             PresentationSource.AddSourceChangedHandler(this, OnSourceChanged);
@@ -158,6 +167,8 @@ namespace Avalonia.Win32.Interop.Wpf
             _ttl.Input?.Invoke(new RawMouseWheelEventArgs(_mouse, (uint) e.Timestamp, _inputRoot,
                 e.GetPosition(this).ToAvaloniaPoint(), new Vector(0, e.Delta), GetModifiers()));
 
+        protected override void OnMouseLeave(MouseEventArgs e) => MouseEvent(RawMouseEventType.LeaveWindow, e);
+
         protected override void OnKeyDown(KeyEventArgs e)
             => _ttl.Input?.Invoke(new RawKeyEventArgs(_keyboard, (uint) e.Timestamp, RawKeyEventType.KeyDown,
                 (Key) e.Key,