Skip to content

Commit

Permalink
Merge pull request #383 from punker76/fix/336
Browse files Browse the repository at this point in the history
Fix item selection/deselection in ItemsControl (inside TabControl) when multiple/extended selection is enabled
  • Loading branch information
punker76 authored Aug 17, 2021
2 parents 40f1ea9 + f62baab commit 693159e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 21 deletions.
7 changes: 0 additions & 7 deletions src/GongSolutions.WPF.DragDrop/DragDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,6 @@ private static void DoMouseButtonUp(object sender, MouseButtonEventArgs e)

private static void DragSourceUp(object sender, Point elementPosition)
{
if (sender is TabControl && !HitTestUtilities.HitTest4Type<TabPanel>(sender, elementPosition))
{
_dragInfo = null;
_clickSupressItem = null;
return;
}

var dragInfo = _dragInfo;

// If we prevented the control's default selection handling in DragSource_PreviewMouseLeftButtonDown
Expand Down
22 changes: 12 additions & 10 deletions src/GongSolutions.WPF.DragDrop/DropInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ public DropInfo(object sender, DragEventArgs e, [CanBeNull] DragInfo dragInfo, E
this.TargetCollection = tvItem.ItemsSource ?? tvItem.Items;
this.InsertIndex = this.TargetCollection != null ? this.TargetCollection.OfType<object>().Count() : 0;
}

this.InsertPosition |= RelativeInsertPosition.TargetItemCenter;
}
//System.Diagnostics.Debug.WriteLine("==> DropInfo: pos={0}, idx={1}, Y={2}, Item={3}", this.InsertPosition, this.InsertIndex, currentYPos, item);
Expand Down Expand Up @@ -217,6 +218,7 @@ public DropInfo(object sender, DragEventArgs e, [CanBeNull] DragInfo dragInfo, E
this.TargetCollection = tvItem.ItemsSource ?? tvItem.Items;
this.InsertIndex = this.TargetCollection != null ? this.TargetCollection.OfType<object>().Count() : 0;
}

this.InsertPosition |= RelativeInsertPosition.TargetItemCenter;
}
//System.Diagnostics.Debug.WriteLine("==> DropInfo: pos={0}, idx={1}, X={2}, Item={3}", this.InsertPosition, this.InsertIndex, currentXPos, item);
Expand Down Expand Up @@ -282,6 +284,7 @@ public int UnfilteredInsertIndex
}
}
}

return insertIndex;
}
}
Expand Down Expand Up @@ -338,24 +341,23 @@ public bool IsSameDragDropContextAsSource
get
{
// Check if DragInfo stuff exists
if (this.DragInfo == null || this.DragInfo.VisualSource == null)
if (this.DragInfo?.VisualSource is null)
{
return true;
}

// A target should be exists
if (this.VisualTarget == null)
if (this.VisualTarget is null)
{
return true;
}

// Source element has a drag context constraint, we need to check the target property matches.
var sourceContext = this.DragInfo.VisualSource.GetValue(DragDrop.DragDropContextProperty) as string;
if (String.IsNullOrEmpty(sourceContext))
{
return true;
}
var targetContext = this.VisualTarget.GetValue(DragDrop.DragDropContextProperty) as string;
return string.Equals(sourceContext, targetContext);
var sourceContext = DragDrop.GetDragDropContext(this.DragInfo.VisualSource);
var targetContext = DragDrop.GetDragDropContext(this.VisualTarget);

return string.Equals(sourceContext, targetContext)
|| string.IsNullOrEmpty(targetContext);
}
}

Expand All @@ -371,4 +373,4 @@ public enum RelativeInsertPosition
AfterTargetItem = 2,
TargetItemCenter = 4
}
}
}
24 changes: 20 additions & 4 deletions src/GongSolutions.WPF.DragDrop/Utilities/VisualTreeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,40 @@ public static DependencyObject GetVisualAncestor(this DependencyObject d, Type i
public static T GetVisualDescendent<T>(this DependencyObject d)
where T : DependencyObject
{
return d.GetVisualDescendents<T>().FirstOrDefault();
return d.GetVisualDescendents<T>(null).FirstOrDefault();
}

public static T GetVisualDescendent<T>(this DependencyObject d, string childName)
where T : DependencyObject
{
return d.GetVisualDescendents<T>(childName).FirstOrDefault();
}

public static IEnumerable<T> GetVisualDescendents<T>(this DependencyObject d)
where T : DependencyObject
{
return d.GetVisualDescendents<T>(null);
}

public static IEnumerable<T> GetVisualDescendents<T>(this DependencyObject d, string childName)
where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(d);

for (var n = 0; n < childCount; n++)
{
var child = VisualTreeHelper.GetChild(d, n);

if (child is T)
if (child is T descendent)
{
yield return (T)child;
if (string.IsNullOrEmpty(childName)
|| descendent is IFrameworkInputElement frameworkInputElement && frameworkInputElement.Name == childName)
{
yield return descendent;
}
}

foreach (var match in GetVisualDescendents<T>(child))
foreach (var match in GetVisualDescendents<T>(child, childName))
{
yield return match;
}
Expand Down
82 changes: 82 additions & 0 deletions src/Showcase/Views/Issues.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,88 @@
</DockPanel>
</TabItem>

<TabItem Header="#336">
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Top">
<TextBlock Style="{StaticResource SampleHeaderTextBlockStyle}" Text="Item selection in ItemsControl is not handled" />
<Button CommandParameter="336"
Style="{StaticResource GitHubIssueButtonStyle}"
ToolTip="Open #336 on Github" />
</Grid>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBlock Style="{StaticResource DefaultTextBlockStyle}" Text="Item selection/deselection in ItemsControl should be handled when multiple/extended selection is enabled inside a TabControl." />

<TabControl dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DragDropContext="TabControl">
<TabItem Header="ListBox 1 Extended">
<ListBox dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.UseDefaultEffectDataTemplate="True"
Margin="5"
SelectionMode="Extended">
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
<ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
<ListBoxItem Content="Item 5" />
</ListBox>
</TabItem>
<TabItem Header="ListBox 2 Multiple">
<ListBox dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DragDropContext="ListBox"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.UseDefaultEffectDataTemplate="True"
Margin="5"
SelectionMode="Multiple">
<ListBoxItem Content="Item 11" />
<ListBoxItem Content="Item 12" />
<ListBoxItem Content="Item 13" />
<ListBoxItem Content="Item 14" />
<ListBoxItem Content="Item 15" />
</ListBox>
</TabItem>

<TabItem Header="ListView 1 Extended">
<ListView dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DragDropContext="ListView"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.UseDefaultEffectDataTemplate="True"
Margin="5"
SelectionMode="Extended">
<ListViewItem Content="Item 1" />
<ListViewItem Content="Item 2" />
<ListViewItem Content="Item 3" />
<ListViewItem Content="Item 4" />
<ListViewItem Content="Item 5" />
</ListView>
</TabItem>
<TabItem Header="ListView 2 Multiple">
<ListView dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DragDropContext="ListView"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.UseDefaultEffectDataTemplate="True"
Margin="5"
SelectionMode="Multiple">
<ListViewItem Content="Item 11" />
<ListViewItem Content="Item 12" />
<ListViewItem Content="Item 13" />
<ListViewItem Content="Item 14" />
<ListViewItem Content="Item 15" />
</ListView>
</TabItem>
</TabControl>

</StackPanel>
</ScrollViewer>
</DockPanel>
</TabItem>

<TabItem Header="#296">
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Top">
Expand Down

0 comments on commit 693159e

Please sign in to comment.