Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Directory.packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<PackageVersion Include="MahApps.Metro.IconPacks.FeatherIcons" Version="5.1.0" />
<PackageVersion Include="MahApps.Metro.IconPacks.Material" Version="5.1.0" />
<PackageVersion Include="MahApps.Metro.IconPacks.Octicons" Version="5.1.0" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.37" />
<PackageVersion Include="Faker.Net" Version="2.0.163" />
<PackageVersion Include="Costura.Fody" Version="6.0.0" />

Expand Down
4 changes: 2 additions & 2 deletions src/GongSolutions.WPF.DragDrop/DragDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ private static void OnRealTargetDragLeave(object sender, DragEventArgs e)
dropHandler.DragLeave(dropInfo);
if(_dragInProgress)
{
DropHintHelpers.OnDragLeave(sender, dropHandler, dragInfo);
DropHintHelpers.OnDragLeave(dropHandler, dragInfo, dropInfo);
}
}

Expand Down Expand Up @@ -782,7 +782,7 @@ private static void DropTargetOnDragOver(object sender, DragEventArgs e, EventTy
}

dropHandler.DragOver(dropInfo);
DropHintHelpers.DragOver(sender, dropInfo);
DropHintHelpers.DragOver(dropInfo);

if (dragInfo is not null)
{
Expand Down
11 changes: 5 additions & 6 deletions src/GongSolutions.WPF.DragDrop/DropHintHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ public static void OnDropFinished()
/// </summary>
/// <param name="dropHandler">The <see cref="IDropTarget"/> for the operation</param>
/// <param name="dragInfo">The <see cref="IDragInfo"/> initiating the drag</param>
/// <param name="sender">The target element of the drag</param>
public static void OnDragLeave(object sender, IDropTarget dropHandler, IDragInfo dragInfo)
/// <param name="dropInfo">Drop info containing with target.</param>
public static void OnDragLeave(IDropTarget dropHandler, IDragInfo dragInfo, IDropInfo dropInfo)
{
var wrapper = _dropTargetHintReferences.Find(m => m.Target == sender);
var wrapper = _dropTargetHintReferences.Find(m => m.Target == dropInfo.VisualTarget);
if (wrapper != null)
{
var dropHintInfo = new DropHintInfo(dragInfo);
Expand All @@ -92,10 +92,9 @@ public static void OnDragLeave(object sender, IDropTarget dropHandler, IDragInfo
/// Update drop hint for the current element.
/// </summary>
/// <param name="dropInfo"></param>
/// <param name="sender"></param>
public static void DragOver(object sender, IDropInfo dropInfo)
public static void DragOver(IDropInfo dropInfo)
{
var wrapper = _dropTargetHintReferences.Find(m => m.Target == sender);
var wrapper = _dropTargetHintReferences.Find(m => m.Target == dropInfo.VisualTarget);
if (wrapper != null)
{
UpdateHintAdorner(wrapper, dropInfo.DropTargetHintAdorner, new DropHintData(dropInfo.DropTargetHintState, dropInfo.DropHintText));
Expand Down
36 changes: 36 additions & 0 deletions src/Showcase/Models/ComboBoxDropBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace Showcase.WPF.DragDrop.Models;

using System.Windows;
using System.Windows.Controls;
using Microsoft.Xaml.Behaviors;
using DragDrop = GongSolutions.Wpf.DragDrop.DragDrop;

public class ComboBoxDropBehavior : Behavior<ComboBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}

protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}

private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
if (AssociatedObject.Template.FindName("PART_EditableTextBox", AssociatedObject) is not TextBox textBox)
{
return;
}

// Create and set the custom drop info builder
var dropInfoBuilder = new ComboBoxDropInfoBuilder(AssociatedObject);
DragDrop.SetDropInfoBuilder(textBox, dropInfoBuilder);

// Attach Gong DragDrop manually
DragDrop.SetIsDropTarget(textBox, DragDrop.GetIsDropTarget(AssociatedObject));
}
}
71 changes: 71 additions & 0 deletions src/Showcase/Models/ComboBoxDropHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
namespace Showcase.WPF.DragDrop.Models;

using System.Windows;
using System.Windows.Controls;
using GongSolutions.Wpf.DragDrop;

public class ComboBoxDropHandler : IDropTarget
{
public void DragEnter(IDropInfo dropInfo)
{
// nothing here
}

public void DragLeave(IDropInfo dropInfo)
{
// nothing here
}

private bool IsAcceptedItem(IDragInfo data)
{
return data?.Data is ListBoxItem;
}

public void DropHint(IDropHintInfo dropHintInfo)
{
if (!IsAcceptedItem(dropHintInfo.DragInfo))
{
if (dropHintInfo.DragInfo == null)
{
return;
}

dropHintInfo.DropHintText = "Cannot drop here";
dropHintInfo.DropTargetHintAdorner = DropTargetAdorners.Hint;
dropHintInfo.DropTargetHintState = DropHintState.Error;
return;
}

dropHintInfo.DropHintText = "Drop here";
dropHintInfo.DropTargetHintAdorner = DropTargetAdorners.Hint;
}

public void DragOver(IDropInfo dropInfo)
{
if (!IsAcceptedItem(dropInfo.DragInfo))
{
if (dropInfo.DragInfo == null)
{
return;
}

dropInfo.DropHintText = "Cannot drop here";
dropInfo.DropTargetHintAdorner = DropTargetAdorners.Hint;
dropInfo.DropTargetHintState = DropHintState.Error;
return;
}

dropInfo.DropHintText = "Let go!";
dropInfo.DropTargetHintState = DropHintState.Active;
dropInfo.DropTargetHintAdorner = DropTargetAdorners.Hint;
dropInfo.Effects = DragDropEffects.Copy;
dropInfo.EffectText = "drop";
dropInfo.DestinationText = "Drop";
}

public void Drop(IDropInfo dropInfo)
{
dropInfo.DropTargetAdorner = DropTargetAdorners.Hint;
dropInfo.Effects = DragDropEffects.Copy;
}
}
33 changes: 33 additions & 0 deletions src/Showcase/Models/ComboBoxDropInfoBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Showcase.WPF.DragDrop.Models;

using System.Windows;
using System.Windows.Controls;
using GongSolutions.Wpf.DragDrop;
using GongSolutions.Wpf.DragDrop.Utilities;

/// <summary>
/// Drop info builder for ComboBox to redirect drop information to the ComboBox itself instead
/// of the internal TextBox.
/// </summary>
/// <param name="comboBox"></param>
public class ComboBoxDropInfoBuilder(ComboBox comboBox) : IDropInfoBuilder
{
public IDropInfo CreateDropInfo(object sender, DragEventArgs e, IDragInfo dragInfo, EventType eventType)
{
if (!comboBox.IsEditable)
{
return null;
}

// If the target is the TextBox inside ComboBox, we want to create
// drop info as if the drop happened on the ComboBox itself
if (e.Source is TextBox || (e.Source is UIElement element && element.GetVisualAncestor<TextBox>() != null))
{
e.Source = comboBox;
e.Handled = true;
return new DropInfo(comboBox, e, dragInfo, eventType);
}

return null;
}
}
1 change: 1 addition & 0 deletions src/Showcase/Showcase.WPF.DragDrop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" />
<PackageReference Include="MahApps.Metro.IconPacks.FeatherIcons" />
<PackageReference Include="MahApps.Metro.IconPacks.Material" />
<PackageReference Include="MahApps.Metro.IconPacks.Octicons" />
Expand Down
89 changes: 89 additions & 0 deletions src/Showcase/Views/Issues.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Showcase.WPF.DragDrop.Models"
xmlns:viewModels="clr-namespace:Showcase.WPF.DragDrop.ViewModels"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
d:DataContext="{d:DesignInstance viewModels:MainViewModel}"
d:DesignHeight="400"
d:DesignWidth="600"
Expand Down Expand Up @@ -1248,6 +1249,94 @@
</DockPanel>
</TabItem>

<TabItem Header="#519">
<TabItem.Resources>
<models:ComboBoxDropHandler x:Key="ComboBoxDropHandler"/>
<DataTemplate x:Key="DefaultDropHintTemplate" DataType="{x:Type dd:DropHintData}">
<Border x:Name="RootBorder"
Background="#008000"
BorderBrush="#008000"
BorderThickness="1"
CornerRadius="5">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
Text="{Binding HintText}"
TextWrapping="Wrap" />
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HintState}" Value="Active">
<Setter TargetName="RootBorder" Property="Background" Value="#263B80" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=HintState}" Value="Error">
<Setter TargetName="RootBorder" Property="Background" Value="#8B0000" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabItem.Resources>
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Top">
<TextBlock Style="{StaticResource SampleHeaderTextBlockStyle}" Text="Drop hint not available for TextBox part of ComboBox when IsEditable=true." />
<Button CommandParameter="519"
Style="{StaticResource GitHubPullRequestButtonStyle}"
ToolTip="Open #519 on Github" />
</Grid>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel>

<UniformGrid Columns="3">
<TextBlock Text="#1 allows drop only on glyph" TextWrapping="Wrap"/>
<TextBlock Text="#2 allows on whole (behavior)" TextWrapping="Wrap"/>
<TextBlock Text="#3 allows on whole " TextWrapping="Wrap"/>
<ComboBox IsEditable="True"
Text="IsEditable"
Margin="2"
Width="150"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{StaticResource ComboBoxDropHandler}"
dd:DragDrop.UseDropTargetHint="True"
dd:DragDrop.DropHintDataTemplate="{StaticResource DefaultDropHintTemplate}"
/>
<ComboBox IsEditable="True"
Text="IsEditable Behavior"
Margin="2"
Width="150"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{StaticResource ComboBoxDropHandler}"
dd:DragDrop.UseDropTargetHint="True"
dd:DragDrop.DropHintDataTemplate="{StaticResource DefaultDropHintTemplate}">
<b:Interaction.Behaviors>
<models:ComboBoxDropBehavior />
</b:Interaction.Behaviors>
</ComboBox>
<ComboBox IsEditable="False"
Text="IsEditable False"
Margin="2"
Width="150"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{StaticResource ComboBoxDropHandler}"
dd:DragDrop.UseDropTargetHint="True"
dd:DragDrop.DropHintDataTemplate="{StaticResource DefaultDropHintTemplate}"
/>
</UniformGrid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<ListBox MinWidth="200"
dd:DragDrop.IsDragSource="True">
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
<ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
<ListBoxItem Content="Item 5" />
</ListBox>
</Grid>
</StackPanel>
</ScrollViewer>
</DockPanel>
</TabItem>
</TabControl>

</Grid>
Expand Down
Loading