Problem with drag and drop in XamlHost:NavigationView

Chuck Bohling 346 Reputation points
2020-07-07T01:44:30.82+00:00

I have a WPF app that's using a XamlIsland to host a UWP NavigationView. On my development laptop, and on a Hyper-V VM running on that laptop, everything works fine. But on other systems, there's a positioning problem with selection highlighting on NavigationViewItem's that have drag and drop enabled. Native UWP app's do not have the problem. I posted an similar issue in November 2018 which can be found here. That issue was never resolved.

What happens is that as an item is drag over a menu item, the one it's over is not highlighted but one that's positioned below it is. If the drop is done, the handler for the highlighted item (the wrong one) is called. It's easy to repro the problem with a simple app. The MainWindow xaml looks like this:

<Window x:Class="WpfApp1.MainWindow"
...
<xamlHost:WindowsXamlHost x:Name="NavigationView" Loaded="NavigationView_Loaded"
InitialTypeName="Windows.UI.Xaml.Controls.NavigationView"/>
...

MainWindow.NavigationView_Loaded creates NavigationViewItem's programmatically like this:

var item1 = new NavigationViewItem() { AllowDrop = true };
item1.Content = new TextBlock() { Text = "Item1" };
item1.DragEnter += NVI_DragEnter;
item1.Drop += NVI_Drop;
item1.DragLeave += NVI_DragLeave;
...
navigationView.MenuItems.Add(item1);

I'm using .NET Core 3.1 with Microsoft.Toolkit.Wpf.UI.XamlHost 6.1.1. I tried with .NET Core 3.0 and an older version of XamlHost and had the same problem.

Any idea what's wrong? Why does this work on some systems? How do I fix the problem?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,681 questions
{count} votes

Accepted answer
  1. Chuck Bohling 346 Reputation points
    2020-11-26T20:06:58.79+00:00

    I filed an issue directly with the dev team at github. Here's the issue 283. It's a bug in XamlHost and will not be fixed. If I understand it correctly, drag and drop will not work correctly with any UIElement if the display scale is not 100%. I had to abandon Xaml Islands and go back to WPF.

    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. Chuck Bohling 346 Reputation points
    2020-07-09T20:49:21.97+00:00

    Here's what you need to do. I'm using Visual Studio 2019

    create a new WPF App (.NET Core) C#, Desktop, Windows named "WpfApp1"
    get NuGet package Microsoft.Toolkit.Wpf.UI.XamlHost 6.1.1
    add Application Manifest File (app.manifest) to the project and uncomment Windows 10 supportOS
    replace Main with this attachment 11763-mainwindowxaml.txt
    replace MainWindow.xaml.cs with the code below

    Run the app and drag a file over item1, item2, or item3. On a monitor with 100% display scaling (Settings -> Display -> Scale and layout), the drag highlights the items correctly and the drop changes the window title to item's name. But if you change the monitor to a scaling other than 100%, e.g. 125%, the drag highlighting is wrong as is the drop. It drops over the wrong item.

    using System;  
    using Windows.UI.Xaml.Controls;  
      
    namespace WpfApp1  
    {  
    	public partial class MainWindow : System.Windows.Window  
    	{  
    		public MainWindow()  
    		{  
    			InitializeComponent();  
    		}  
      
    		private void NavigationView_Loaded(object sender, EventArgs e)  
    		{  
    			if (NavigationView.Child is NavigationView navView)  
    			{  
    				navView.OpenPaneLength = 220;  
    				navView.ExpandedModeThresholdWidth = 400;  
    				navView.IsBackButtonVisible = NavigationViewBackButtonVisible.Collapsed;  
      
    				var item1 = new NavigationViewItem() { AllowDrop = true };  
    				item1.Content = new TextBlock() { Text = "Item1" };  
    				item1.DragEnter += NVI_DragEnter;  
    				item1.Drop += NVI_Drop;  
    				item1.DragLeave += NVI_DragLeave;  
      
    				var item2 = new NavigationViewItem() { AllowDrop = true };  
    				item2.Content = new TextBlock() { Text = "Item2" };  
    				item2.DragEnter += NVI_DragEnter;  
    				item2.Drop += NVI_Drop;  
    				item2.DragLeave += NVI_DragLeave;  
      
    				var item3 = new NavigationViewItem() { AllowDrop = true };  
    				item3.Content = new TextBlock() { Text = "Item3" };  
    				item3.DragEnter += NVI_DragEnter;  
    				item3.Drop += NVI_Drop;  
    				item3.DragLeave += NVI_DragLeave;  
      
    				navView.MenuItems.Add(item1);  
    				navView.MenuItems.Add(item2);  
    				navView.MenuItems.Add(item3);  
    			}  
    		}  
      
    		private void NVI_DragEnter(object sender, Windows.UI.Xaml.DragEventArgs args)  
    		{  
    			args.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;  
    		}  
      
    		private void NVI_DragLeave(object sender, Windows.UI.Xaml.DragEventArgs args)  
    		{  
    			args.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.None;  
    		}  
      
    		public void NVI_Drop(object sender, Windows.UI.Xaml.DragEventArgs args)  
    		{  
    			var nvi = sender as NavigationViewItem;  
    			var tb = nvi.Content as TextBlock;  
    			Title = tb.Text;  
    		}  
    	}  
    }  
      
    
    0 comments No comments

  2. Chuck Bohling 346 Reputation points
    2020-07-20T00:05:23.66+00:00

    Where you able to repro the problem?

    0 comments No comments

  3. Chuck Bohling 346 Reputation points
    2020-08-12T18:30:06.097+00:00

    @DaisyTian-MSFT Any update? This appears to be a bug in XamlHost. If I'm correct, drag and drop and NavigationView will not work correctly for any display scaling other than 100%. How is that possible? I've been looking for workarounds but haven't found anything acceptable. This will have a significant negative impact on my app. Please help.

    0 comments No comments