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();
}
private void OnDrop(object sender, DragEventArgs args)
private object CreateDragMessage(object sender, DragEventArgs args)
{
if (Mediator is not null)
{
var dropMessageType = typeof(Drop<>).MakeGenericType(sender.GetType());
var dropMessage = Activator.CreateInstance(dropMessageType, args);
var dropMessageType = typeof(Drag<>).MakeGenericType(sender.GetType());
return 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)
{
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>
</PropertyGroup>
<ItemGroup>
<Compile Include="Drag.cs" />
<Compile Include="DropTarget.cs" />
<Compile Include="DataTemplateFactory.cs" />
<Compile Include="Drop.cs" />
<Compile Include="IDataTemplateFactory.cs" />
<Compile Include="IDragHandler.cs" />
<Compile Include="IDropHandler.cs" />
<Compile Include="IServiceCollectionExtensions.cs" />
<Compile Include="IWindowPrivate.cs" />
@@ -78,6 +78,7 @@
<Compile Include="Controls\TaskbarButtonFlyoutTemplateSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Controls\TaskbarButtonFlyout.cs" />
<Compile Include="Views\TaskbarButtonGroupDragHandler.cs" />
<Compile Include="Views\TaskbarButtonGroupDropHandler.cs" />
<Compile Include="Views\TaskbarButtonGroupItemViewModel.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>
<foundation:DropTarget Mediator="{x:Bind ViewModel.Mediator}" />
</interactivity:Interaction.Behaviors>
<StackPanel AllowDrop="True" Background="Red">
<StackPanel AllowDrop="True">
<TextBox HorizontalAlignment="Stretch" Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />
<GridView
x:Name="GridView"
+1
View File
@@ -41,6 +41,7 @@ namespace TheXamlGuy.TaskbarGroup
.AddTransient<TaskbarButtonView>()
.AddTransient<TaskbarButtonViewModel>()
.AddTransient<TaskbarButtonGroupView>()
.AddAsyncHandler<TaskbarButtonGroupDragHandler>()
.AddAsyncHandler<TaskbarButtonGroupDropHandler>()
.AddTransient<TaskbarButtonGroupViewModel>();
}
@@ -2,21 +2,29 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using TheXamlGuy.TaskbarGroup.Core;
namespace TheXamlGuy.TaskbarGroup
{
public sealed class ApplicationHost : IHostedService
{
private readonly IEnumerable<IInitializable> initializables;
private bool isInitialized;
private readonly TaskbarButtonFlyoutWindow flyoutWindow;
private readonly IEnumerable<IInitializable> initializables;
private readonly IMediator mediator;
private bool isInitialized;
public ApplicationHost(IEnumerable<IInitializable> initializables,
IMessenger messenger,
IMediator mediator,
TaskbarButtonFlyoutWindow flyoutWindow)
{
this.initializables = initializables;
this.mediator = mediator;
this.flyoutWindow = flyoutWindow;
messenger.Subscribe<TaskbarButtonInvoked>(OnTaskbarButtonInvoked);
messenger.Subscribe<TaskbarButtonDragEnter>(OnTaskbarButtonDragEnter);
}
public async Task StartAsync(CancellationToken cancellationToken)
@@ -27,11 +35,11 @@ namespace TheXamlGuy.TaskbarGroup
isInitialized = true;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await Task.CompletedTask;
}
private async Task InitializeAsync()
{
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()
{
if (!isInitialized)
{
flyoutWindow.Show();
await Task.CompletedTask;
}
}
@@ -64,6 +64,7 @@ namespace TheXamlGuy.TaskbarGroup
flyout.ShowAt(placement);
}
window.Show();
window.Activate();
}
}
@@ -2,29 +2,24 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using TheXamlGuy.TaskbarGroup.Core;
using TheXamlGuy.TaskbarGroup.Flyout.Controls;
namespace TheXamlGuy.TaskbarGroup
{
public class TaskbarButtonFlyoutWindow : TransparentXamlWindow<TaskbarButtonFlyout>
{
private readonly IMediator mediator;
private bool isDpiChanging;
public TaskbarButtonFlyoutWindow(IMessenger messenger,
IMediator mediator)
public TaskbarButtonFlyoutWindow()
{
this.mediator = mediator;
DpiChanged += OnDpiChanged;
Deactivated += OnDeactivated;
Topmost = true;
Width = 258;
Height = 258;
messenger.Subscribe<TaskbarButtonInvoked>(OnTaskbarButtonInvoked);
messenger.Subscribe<TaskbarButtonDragEnter>(OnTaskbarButtonDragEnter);
Dispatcher.BeginInvoke(new Action(() =>
{
Hide();
}), DispatcherPriority.ContextIdle, null);
}
private void OnDeactivated(object? sender, EventArgs args)
@@ -32,49 +27,8 @@ namespace TheXamlGuy.TaskbarGroup
if (XamlContent is TaskbarButtonFlyout flyout)
{
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 System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
namespace TheXamlGuy.TaskbarGroup
{
public class XamlWindow<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement
{
private bool isDpiChanging;
private WindowsXamlHost? xamlHost;
public XamlWindow()
{
Initialize();
DpiChanged += OnDpiChanged;
}
public TXamlContent? XamlContent
@@ -37,5 +42,32 @@ namespace TheXamlGuy.TaskbarGroup
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);
});
}
}
}