From 3126901721ea3f20c4c2c784cbc9f4dcf1e8ceea Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 7 Jun 2017 17:36:01 +0300 Subject: [PATCH] WPF embedding improvements --- .../WindowsInteropTest/EmbedToWpfDemo.xaml | 11 ++++++ .../WindowsInteropTest/EmbedToWpfDemo.xaml.cs | 5 +++ src/Avalonia.Layout/Layoutable.cs | 2 +- .../Avalonia.Win32.Interop.csproj | 12 +++++++ .../Wpf/WpfAvaloniaHost.cs | 35 +++++++++++++++---- .../Wpf/WpfTopLevelImpl.cs | 11 ++++++ 6 files changed, 69 insertions(+), 7 deletions(-) diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml index 5a346d4e8d..1d8dc32a69 100644 --- a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml +++ b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml @@ -1,6 +1,7 @@  + + + + + + + + + + diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs index eebd18dece..636d89dc70 100644 --- a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs +++ b/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 += "!"; + }; } } diff --git a/src/Avalonia.Layout/Layoutable.cs b/src/Avalonia.Layout/Layoutable.cs index 20050058bf..3f6d789877 100644 --- a/src/Avalonia.Layout/Layoutable.cs +++ b/src/Avalonia.Layout/Layoutable.cs @@ -370,7 +370,7 @@ namespace Avalonia.Layout /// /// Invalidates the measurement of the control and queues a new layout pass. /// - public void InvalidateMeasure() + public virtual void InvalidateMeasure() { if (IsMeasureValid) { diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index ae61fc697f..e2d764c62c 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -68,6 +68,10 @@ {d2221c82-4a25-4583-9b43-d791e3f6820c} Avalonia.Controls + + {4a1abb09-9047-4bd5-a4ad-a055e52c5ee0} + Avalonia.DotNetFrameworkRuntime + {62024b2d-53eb-4638-b26b-85eeaa54866e} Avalonia.Input @@ -92,6 +96,14 @@ {fb05ac90-89ba-4f2f-a924-f37875fb547c} Avalonia.Cairo + + {3e53a01a-b331-47f3-b828-4a5717e77a24} + Avalonia.Markup.Xaml + + + {6417e941-21bc-467b-a771-0de389353ce6} + Avalonia.Markup + {811a76cf-1cf6-440f-963b-bbe31bd72a82} Avalonia.Win32 diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs index 2d350fbe30..4f85a326f0 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs +++ b/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) + { + // + } } } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 56dc26992e..c82b71d3a5 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/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,