Reorg window handling and add drag handler

This commit is contained in:
dan_clark@outlook.com
2022-03-23 22:18:36 +00:00
parent 263704a772
commit 04df2d2ff6
12 changed files with 135 additions and 65 deletions
@@ -0,0 +1,9 @@
using Windows.UI.Xaml;
namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation
{
public record class Drag<TTarget>(DragEventArgs DragEventArgs) where TTarget : UIElement
{
public TTarget Target { get; }
}
}
@@ -30,20 +30,34 @@ namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation
base.OnAttached(); base.OnAttached();
} }
private void OnDrop(object sender, DragEventArgs args) private object CreateDragMessage(object sender, DragEventArgs args)
{ {
if (Mediator is not null) var dropMessageType = typeof(Drag<>).MakeGenericType(sender.GetType());
{ return Activator.CreateInstance(dropMessageType, args);
var dropMessageType = typeof(Drop<>).MakeGenericType(sender.GetType()); }
var dropMessage = Activator.CreateInstance(dropMessageType, args);
Mediator.HandleAsync(dropMessage); private object CreateDropMessage(object sender, DragEventArgs args)
} {
var dropMessageType = typeof(Drop<>).MakeGenericType(sender.GetType());
return Activator.CreateInstance(dropMessageType, args);
} }
private void OnDragOver(object sender, DragEventArgs args) private void OnDragOver(object sender, DragEventArgs args)
{ {
args.AcceptedOperation = DataPackageOperation.Link; if (Mediator is not null)
{
var message = CreateDragMessage(sender, args);
Mediator.HandleAsync(message);
}
}
private void OnDrop(object sender, DragEventArgs args)
{
if (Mediator is not null)
{
var message = CreateDropMessage(sender, args);
Mediator.HandleAsync(message);
}
} }
} }
} }
@@ -0,0 +1,10 @@
using TheXamlGuy.TaskbarGroup.Core;
using Windows.UI.Xaml;
namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation
{
public interface IDragHandler<TTarget> : IAsyncMessageHandler<Drag<TTarget>> where TTarget : UIElement
{
}
}
@@ -122,10 +122,12 @@
<RestoreProjectStyle>PackageReference</RestoreProjectStyle> <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Drag.cs" />
<Compile Include="DropTarget.cs" /> <Compile Include="DropTarget.cs" />
<Compile Include="DataTemplateFactory.cs" /> <Compile Include="DataTemplateFactory.cs" />
<Compile Include="Drop.cs" /> <Compile Include="Drop.cs" />
<Compile Include="IDataTemplateFactory.cs" /> <Compile Include="IDataTemplateFactory.cs" />
<Compile Include="IDragHandler.cs" />
<Compile Include="IDropHandler.cs" /> <Compile Include="IDropHandler.cs" />
<Compile Include="IServiceCollectionExtensions.cs" /> <Compile Include="IServiceCollectionExtensions.cs" />
<Compile Include="IWindowPrivate.cs" /> <Compile Include="IWindowPrivate.cs" />
@@ -78,6 +78,7 @@
<Compile Include="Controls\TaskbarButtonFlyoutTemplateSettings.cs" /> <Compile Include="Controls\TaskbarButtonFlyoutTemplateSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Controls\TaskbarButtonFlyout.cs" /> <Compile Include="Controls\TaskbarButtonFlyout.cs" />
<Compile Include="Views\TaskbarButtonGroupDragHandler.cs" />
<Compile Include="Views\TaskbarButtonGroupDropHandler.cs" /> <Compile Include="Views\TaskbarButtonGroupDropHandler.cs" />
<Compile Include="Views\TaskbarButtonGroupItemViewModel.cs" /> <Compile Include="Views\TaskbarButtonGroupItemViewModel.cs" />
<Compile Include="Views\TaskbarButtonGroupView.xaml.cs"> <Compile Include="Views\TaskbarButtonGroupView.xaml.cs">
@@ -0,0 +1,24 @@
using System.Threading;
using System.Threading.Tasks;
using TheXamlGuy.TaskbarGroup.Flyout.Foundation;
using Windows.ApplicationModel.DataTransfer;
namespace TheXamlGuy.TaskbarGroup.Flyout
{
public class TaskbarButtonGroupDragHandler : IDragHandler<TaskbarButtonGroupView>
{
public Task Handle(Drag<TaskbarButtonGroupView> message, CancellationToken canellationToken = default)
{
message.DragEventArgs.AcceptedOperation = DataPackageOperation.Link;
if (message.DragEventArgs.DragUIOverride is not null)
{
message.DragEventArgs.DragUIOverride.IsContentVisible = true;
message.DragEventArgs.DragUIOverride.IsGlyphVisible = false;
message.DragEventArgs.DragUIOverride.IsCaptionVisible = false;
}
return Task.CompletedTask;
}
}
}
@@ -8,7 +8,7 @@
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<foundation:DropTarget Mediator="{x:Bind ViewModel.Mediator}" /> <foundation:DropTarget Mediator="{x:Bind ViewModel.Mediator}" />
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
<StackPanel AllowDrop="True" Background="Red"> <StackPanel AllowDrop="True">
<TextBox HorizontalAlignment="Stretch" Text="{x:Bind ViewModel.Name, Mode=TwoWay}" /> <TextBox HorizontalAlignment="Stretch" Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />
<GridView <GridView
x:Name="GridView" x:Name="GridView"
+1
View File
@@ -41,6 +41,7 @@ namespace TheXamlGuy.TaskbarGroup
.AddTransient<TaskbarButtonView>() .AddTransient<TaskbarButtonView>()
.AddTransient<TaskbarButtonViewModel>() .AddTransient<TaskbarButtonViewModel>()
.AddTransient<TaskbarButtonGroupView>() .AddTransient<TaskbarButtonGroupView>()
.AddAsyncHandler<TaskbarButtonGroupDragHandler>()
.AddAsyncHandler<TaskbarButtonGroupDropHandler>() .AddAsyncHandler<TaskbarButtonGroupDropHandler>()
.AddTransient<TaskbarButtonGroupViewModel>(); .AddTransient<TaskbarButtonGroupViewModel>();
} }
@@ -2,21 +2,29 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using TheXamlGuy.TaskbarGroup.Core; using TheXamlGuy.TaskbarGroup.Core;
namespace TheXamlGuy.TaskbarGroup namespace TheXamlGuy.TaskbarGroup
{ {
public sealed class ApplicationHost : IHostedService public sealed class ApplicationHost : IHostedService
{ {
private readonly IEnumerable<IInitializable> initializables;
private bool isInitialized;
private readonly TaskbarButtonFlyoutWindow flyoutWindow; private readonly TaskbarButtonFlyoutWindow flyoutWindow;
private readonly IEnumerable<IInitializable> initializables;
private readonly IMediator mediator;
private bool isInitialized;
public ApplicationHost(IEnumerable<IInitializable> initializables, public ApplicationHost(IEnumerable<IInitializable> initializables,
IMessenger messenger,
IMediator mediator,
TaskbarButtonFlyoutWindow flyoutWindow) TaskbarButtonFlyoutWindow flyoutWindow)
{ {
this.initializables = initializables; this.initializables = initializables;
this.mediator = mediator;
this.flyoutWindow = flyoutWindow; this.flyoutWindow = flyoutWindow;
messenger.Subscribe<TaskbarButtonInvoked>(OnTaskbarButtonInvoked);
messenger.Subscribe<TaskbarButtonDragEnter>(OnTaskbarButtonDragEnter);
} }
public async Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken)
@@ -27,11 +35,11 @@ namespace TheXamlGuy.TaskbarGroup
isInitialized = true; isInitialized = true;
} }
public async Task StopAsync(CancellationToken cancellationToken) public async Task StopAsync(CancellationToken cancellationToken)
{ {
await Task.CompletedTask; await Task.CompletedTask;
} }
private async Task InitializeAsync() private async Task InitializeAsync()
{ {
if (!isInitialized) if (!isInitialized)
@@ -45,12 +53,26 @@ namespace TheXamlGuy.TaskbarGroup
} }
} }
private void OnTaskbarButtonDragEnter(TaskbarButtonDragEnter args)
{
Application.Current.Dispatcher.Invoke(() => Open(args.Button));
}
private void OnTaskbarButtonInvoked(TaskbarButtonInvoked args)
{
Application.Current.Dispatcher.Invoke(() => Open(args.Button));
}
private void Open(TaskbarButton button)
{
mediator.Handle(new TaskbarButtonFlyoutActivation(button));
}
private async Task StartupAsync() private async Task StartupAsync()
{ {
if (!isInitialized) if (!isInitialized)
{ {
flyoutWindow.Show(); flyoutWindow.Show();
await Task.CompletedTask; await Task.CompletedTask;
} }
} }
@@ -64,6 +64,7 @@ namespace TheXamlGuy.TaskbarGroup
flyout.ShowAt(placement); flyout.ShowAt(placement);
} }
window.Show();
window.Activate(); window.Activate();
} }
} }
@@ -2,29 +2,24 @@
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using TheXamlGuy.TaskbarGroup.Core;
using TheXamlGuy.TaskbarGroup.Flyout.Controls; using TheXamlGuy.TaskbarGroup.Flyout.Controls;
namespace TheXamlGuy.TaskbarGroup namespace TheXamlGuy.TaskbarGroup
{ {
public class TaskbarButtonFlyoutWindow : TransparentXamlWindow<TaskbarButtonFlyout> public class TaskbarButtonFlyoutWindow : TransparentXamlWindow<TaskbarButtonFlyout>
{ {
private readonly IMediator mediator;
private bool isDpiChanging;
public TaskbarButtonFlyoutWindow(IMessenger messenger, public TaskbarButtonFlyoutWindow()
IMediator mediator)
{ {
this.mediator = mediator;
DpiChanged += OnDpiChanged;
Deactivated += OnDeactivated; Deactivated += OnDeactivated;
Topmost = true; Topmost = true;
Width = 258; Width = 258;
Height = 258; Height = 258;
messenger.Subscribe<TaskbarButtonInvoked>(OnTaskbarButtonInvoked); Dispatcher.BeginInvoke(new Action(() =>
messenger.Subscribe<TaskbarButtonDragEnter>(OnTaskbarButtonDragEnter); {
Hide();
}), DispatcherPriority.ContextIdle, null);
} }
private void OnDeactivated(object? sender, EventArgs args) private void OnDeactivated(object? sender, EventArgs args)
@@ -32,49 +27,8 @@ namespace TheXamlGuy.TaskbarGroup
if (XamlContent is TaskbarButtonFlyout flyout) if (XamlContent is TaskbarButtonFlyout flyout)
{ {
flyout.Close(); flyout.Close();
Hide();
} }
} }
private async void OnDpiChanged(object sender, DpiChangedEventArgs args)
{
if (isDpiChanging) return;
isDpiChanging = true;
await Dispatcher.Invoke(async () =>
{
Visibility = Visibility.Visible;
await Dispatcher.BeginInvoke(new Action(() =>
{
VisualTreeHelper.SetRootDpi(this, args.OldDpi);
}), DispatcherPriority.ContextIdle, null);
await Dispatcher.BeginInvoke(new Action(() =>
{
VisualTreeHelper.SetRootDpi(this, args.NewDpi);
}), DispatcherPriority.ContextIdle, null);
await Dispatcher.BeginInvoke(new Action(() =>
{
Visibility = Visibility.Hidden;
isDpiChanging = false;
}), DispatcherPriority.ContextIdle, null);
});
}
private void OnTaskbarButtonDragEnter(TaskbarButtonDragEnter args)
{
Dispatcher.Invoke(() => Open(args.Button));
}
private void OnTaskbarButtonInvoked(TaskbarButtonInvoked args)
{
Dispatcher.Invoke(() => Open(args.Button));
}
private void Open(TaskbarButton button)
{
mediator.Handle(new TaskbarButtonFlyoutActivation(button));
}
} }
} }
@@ -1,15 +1,20 @@
using Microsoft.Toolkit.Wpf.UI.XamlHost; using Microsoft.Toolkit.Wpf.UI.XamlHost;
using System;
using System.Windows; using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
namespace TheXamlGuy.TaskbarGroup namespace TheXamlGuy.TaskbarGroup
{ {
public class XamlWindow<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement public class XamlWindow<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement
{ {
private bool isDpiChanging;
private WindowsXamlHost? xamlHost; private WindowsXamlHost? xamlHost;
public XamlWindow() public XamlWindow()
{ {
Initialize(); Initialize();
DpiChanged += OnDpiChanged;
} }
public TXamlContent? XamlContent public TXamlContent? XamlContent
@@ -37,5 +42,32 @@ namespace TheXamlGuy.TaskbarGroup
Content = xamlHost; Content = xamlHost;
} }
private async void OnDpiChanged(object sender, DpiChangedEventArgs args)
{
if (isDpiChanging) return;
isDpiChanging = true;
await Dispatcher.Invoke(async () =>
{
Visibility = Visibility.Visible;
await Dispatcher.BeginInvoke(new Action(() =>
{
VisualTreeHelper.SetRootDpi(this, args.OldDpi);
}), DispatcherPriority.ContextIdle, null);
await Dispatcher.BeginInvoke(new Action(() =>
{
VisualTreeHelper.SetRootDpi(this, args.NewDpi);
}), DispatcherPriority.ContextIdle, null);
await Dispatcher.BeginInvoke(new Action(() =>
{
Visibility = Visibility.Hidden;
isDpiChanging = false;
}), DispatcherPriority.ContextIdle, null);
});
}
} }
} }