How to replace Cursor with Path geometry on DragOver/DragEnter

Emon Haque 3,176 Reputation points
2020-11-23T10:16:16.993+00:00

I've a Custom Control, DropBox based on ListBox, and it lets me drop one or more files. When I select one or more files and drag those over the DropBox, Cursor becomes a square and it doesn't matter whether the dragged item is valid, it always turns into a square as soon as the cursor enters the droppable region:

41901-test1.gif

I want to use Path Geometries instead of the default Cursor. For example, when the dragged item is valid (i.e. file) I want the the string plus, Path Geometry, as the Cursor and if it isn't valid (i.e. folder) I want to use another Path Geometry. Here's the DropBox.cs and the record for ItemsSource:

record Attachment(string Path, string Name, long Size);  
public class DropBox : ListBox  
{  
    //string plus = "M10.6 13.4A1 1 0 0 1 9.2 14.8A4.8 4.8 0 0 1 9.2 7.8L12.7 4.2A5.1 5.1 0 0 1 19.8 4.2A5.1 5.1 0 0 1 19.8 11.3L18.3 12.8A6.4 6.4 0 0 0 17.9 10.4L18.4 9.9A3.2 3.2 0 0 0 18.4 5.6A3.2 3.2 0 0 0 14.1 5.6L10.6 9.2A2.9 2.9 0 0 0 10.6 13.4M23 18V20H20V23H18V20H15V18H18V15H20V18M16.2 13.7A4.8 4.8 0 0 0 14.8 9.2A1 1 0 0 0 13.4 10.6A2.9 2.9 0 0 1 13.4 14.8L9.9 18.4A3.2 3.2 0 0 1 5.6 18.4A3.2 3.2 0 0 1 5.6 14.1L6.1 13.7A7.3 7.3 0 0 1 5.7 11.2L4.2 12.7A5.1 5.1 0 0 0 4.2 19.8A5.1 5.1 0 0 0 11.3 19.8L13.1 18A6 6 0 0 1 16.2 13.7Z";  
    ObservableCollection<Attachment> collection = new();  
    public ICommand Remove { get; set; }  
    static DropBox()  
    {  
        DefaultStyleKeyProperty.OverrideMetadata(typeof(DropBox), new FrameworkPropertyMetadata(typeof(DropBox)));  
    }  
    public override void OnApplyTemplate()  
    {  
        base.OnApplyTemplate();  
        AllowDrop = true;  
        ItemsSource = collection;  
        Remove = new Command(remove, (o) => true);  
    }  
    void remove(object o) => collection.Remove((Attachment)o);  
    protected override void OnDrop(DragEventArgs e)  
    {  
        var files = (string[])e.Data.GetData(DataFormats.FileDrop);  
        foreach (var file in files)  
            collection.Add(new(file, file.Substring(file.LastIndexOf('\\') + 1), new FileInfo(file).Length));  
    }  
    //protected override void OnDragOver(DragEventArgs e) => Cursor = new Cursor(plus);  
}  

and here's the xaml in Themes\Generic.xaml:

<Style BasedOn="{StaticResource {x:Type ListBox}}" TargetType="{x:Type local:DropBox}">  
    <Setter Property="ItemContainerStyle">  
        <Setter.Value>  
            <Style TargetType="ListBoxItem">  
                <Setter Property="FocusVisualStyle" Value="{x:Null}"/>  
                <Setter Property="Template">  
                    <Setter.Value>  
                        <ControlTemplate TargetType="ListBoxItem">  
                            <Grid Background="Transparent" ToolTip="{Binding Path}">  
                                <Grid.ColumnDefinitions>  
                                    <ColumnDefinition Width="*"/>  
                                    <ColumnDefinition Width="Auto"/>  
                                    <ColumnDefinition Width="Auto"/>  
                                </Grid.ColumnDefinitions>  
                                <TextBlock Text="{Binding Name}"/>  
                                <TextBlock Grid.Column="1" Text="{Binding Size, StringFormat=N0}"/>  
                                <Button Grid.Column="2" Content=" - " Margin="5 0 0 0" CommandParameter="{Binding}" Command="{Binding Remove, RelativeSource={RelativeSource AncestorType=local:DropBox}}"/>  
                            </Grid>  
                        </ControlTemplate>  
                    </Setter.Value>  
                </Setter>  
            </Style>  
        </Setter.Value>  
    </Setter>  
</Style>  
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,667 questions
{count} votes

Accepted answer
  1. Jeffrey Chen 81 Reputation points
    2021-01-21T09:51:01.16+00:00

    @Emon Haque we test and find it's not possible to change the cursor as the cursor can only affected by the source file/ folder which you drag and drop. you can refer https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-enabling-drag-and-drop-on-a-user-control?view=netframeworkdesktop-4.8

    59104-image.png

    in this demo, we choose to drag the blue circle element to the textbox, and find the cursor can only be changed via OnGiveFeedback event
    59095-image.png

    so the cursor is changed based on the code of the file and folder.

    1 person found this answer helpful.
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Emon Haque 3,176 Reputation points
    2020-12-03T15:44:02.87+00:00

    I've added a RichTextBox and a ToolBar in my DropBox and noticed a few more issues.

    1) When I select text in RichTextBox and click on Bold icon, it changes the selected text's style but the Bold Icon remains in Focus/Highlighted (changes from black to blue and remains blue until I click on another ToolButton) even if I change style with keyboard shortcut (Ctrl+B). This is the behavior for all ToolBar Icons

    2) By default I can't drop file(s) on RichTextBox. I've tried hooking up an event like this:

            message = (RichTextBox)GetTemplateChild("message");  
            message.DragOver += OnDragOverMessage;  
    

    But this DragOver doesn't work, I've to add the handler this way:

            message.AddHandler(DragOverEvent, new DragEventHandler(OnDragOverMessage), true);  
    

    the last true argument is the key to make it work and in addition to that I've to have these in my eventhandler:

        void OnDragOverMessage(object sender, DragEventArgs e)  
        {  
            if (e.Data.GetDataPresent(DataFormats.FileDrop))  
                e.Effects = DragDropEffects.Copy;  
            else e.Effects = DragDropEffects.None;  
        }  
    

    Now with these in OnDragOverMessage, it allows dropping files as well as folder! To prevent folder drop, I've to have a check for FileAttributes in OnDrop function:

        protected override void OnDrop(DragEventArgs e)  
        {  
            var files = (string[])e.Data.GetData(DataFormats.FileDrop);  
            foreach (var file in files)  
            {  
                if (File.GetAttributes(file).HasFlag(FileAttributes.Directory)) continue;  
                Collection.Add(new(file, file.Substring(file.LastIndexOf('\\') + 1), new FileInfo(file).Length));  
            }   
        }  
    

    44853-test.gif

    I've uploaded a .zip file BUT not sure whether it's been uploaded or not, I don't see that when I go to the link provided! Do you see that?


  2. Jeffrey Chen 81 Reputation points
    2021-01-11T10:32:24.957+00:00

    @Emon Haque have you tried to change the cursor based on file type as below:
    55441-2021-01-11-18h29-16.png

    if this is your original request?

    Thanks,
    Jeffrey