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,823 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


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.