✨ 增加可拖动到其它菜单功能 ⚡ 切换了icon动画
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:GeekDesk.Control.UserControls.PannelCard"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:cvt="clr-namespace:GeekDesk.Converts"
|
||||
xmlns:cst="clr-namespace:GeekDesk.Constant"
|
||||
xmlns:DraggAnimatedPanel="clr-namespace:DraggAnimatedPanel"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
@@ -21,6 +22,11 @@
|
||||
<SolidColorBrush Color="Black" Opacity="0.01"/>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="AllowDrop" Value="True"/>
|
||||
<EventSetter Event="Drop" Handler="Menu_Drop"/>
|
||||
<EventSetter Event="PreviewDragEnter" Handler="Menu_PreviewDragEnter"/>
|
||||
<EventSetter Event="PreviewDragLeave" Handler="Menu_PreviewDragLeave"/>
|
||||
<EventSetter Event="MouseLeave" Handler="Menu_MouseLeave"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
|
||||
<EventSetter Event="MouseEnter" Handler="Menu_MouseEnter"/>
|
||||
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBoxItem_MouseDown"/>
|
||||
@@ -71,16 +77,48 @@
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
</Trigger>-->
|
||||
<Trigger Property="IsMouseOver" Value="False">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Background" Value="#00FFFFFF"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
</Trigger>
|
||||
|
||||
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style x:Key="MyPoptipStyle" TargetType="Border">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{StaticResource DefaultCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
|
||||
<!--<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="hc:Poptip">
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>-->
|
||||
</Style>
|
||||
|
||||
<cvt:MenuWidthConvert x:Key="MenuWidthConvert"/>
|
||||
<cvt:OpcityConvert x:Key="OpcityConvert"/>
|
||||
<cvt:StringAppendConvert x:Key="StringAppendConvert"/>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="Transparent">
|
||||
<Popup Name="MyPoptip" FlowDirection="LeftToRight"
|
||||
PopupAnimation="None" Placement="Mouse" IsOpen="False"
|
||||
AllowsTransparency="True"
|
||||
>
|
||||
<Grid Background="Transparent">
|
||||
<Border Style="{StaticResource MyPoptipStyle}">
|
||||
<TextBlock Name="MyPoptipContent" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Text="Test" FontSize="19"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Popup>
|
||||
|
||||
<!--左侧栏-->
|
||||
<hc:Card x:Name="MyCard"
|
||||
BorderThickness="1"
|
||||
@@ -101,7 +139,12 @@
|
||||
<MenuItem Header="新建菜单" Click="CreateMenu"/>
|
||||
</ContextMenu>
|
||||
</hc:Card.ContextMenu>
|
||||
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
|
||||
|
||||
|
||||
|
||||
<ListBox x:Name="MenuListBox"
|
||||
Padding="2,3,0,2"
|
||||
ItemsSource="{Binding MenuList}"
|
||||
@@ -138,7 +181,8 @@
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Tag="{Binding}">
|
||||
<StackPanel Tag="{Binding}"
|
||||
>
|
||||
<TextBox Text="{Binding Path=MenuName, Mode=TwoWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBox},AncestorLevel=1},Path=Tag, Mode=TwoWay, Converter={StaticResource MenuWidthConvert}, ConverterParameter=35}"
|
||||
@@ -177,4 +221,5 @@
|
||||
</ListBox>
|
||||
</WrapPanel>
|
||||
</hc:Card>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -312,6 +312,9 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
private void Menu_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (IS_EDIT) return;
|
||||
|
||||
MainWindow.mainWindow.RightCard.WrapCard.Visibility = Visibility.Collapsed;
|
||||
|
||||
//设置对应菜单的图标列表
|
||||
if (MenuListBox.SelectedIndex == -1)
|
||||
{
|
||||
@@ -321,6 +324,7 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
{
|
||||
appData.AppConfig.SelectedMenuIcons = appData.MenuList[MenuListBox.SelectedIndex].IconList;
|
||||
}
|
||||
MainWindow.mainWindow.RightCard.WrapCard.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
|
||||
@@ -427,5 +431,35 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
MenuListBox.SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Menu_PreviewDragLeave(object sender, DragEventArgs e)
|
||||
{
|
||||
MyPoptip.IsOpen = false;
|
||||
}
|
||||
|
||||
private void Menu_PreviewDragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
MenuInfo mi = (sender as ListBoxItem).DataContext as MenuInfo;
|
||||
MyPoptipContent.Text = "移动至:" + mi.MenuName;
|
||||
MyPoptip.VerticalOffset = 30;
|
||||
MyPoptip.IsOpen = true;
|
||||
}
|
||||
|
||||
private void Menu_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
MyPoptip.IsOpen = false;
|
||||
}
|
||||
|
||||
private void Menu_Drop(object sender, DragEventArgs e)
|
||||
{
|
||||
MyPoptip.IsOpen = false;
|
||||
|
||||
MenuInfo mi = (sender as ListBoxItem).DataContext as MenuInfo;
|
||||
IconInfo iconInfo = (IconInfo)e.Data.GetData(typeof(IconInfo));
|
||||
|
||||
appData.MenuList[MenuListBox.SelectedIndex].IconList.Remove(iconInfo);
|
||||
appData.MenuList[MenuListBox.Items.IndexOf(mi)].IconList.Add(iconInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,15 +19,6 @@
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>-->
|
||||
|
||||
<Storyboard x:Key="Custom1Transition" x:Shared="False">
|
||||
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ElasticEase Oscillations="1"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
|
||||
<Style x:Key="ImageStyle" TargetType="Image">
|
||||
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageWidth, Mode=OneWay}"/>
|
||||
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageHeight, Mode=OneWay}"/>
|
||||
@@ -46,6 +37,29 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Storyboard x:Key="Custom1Transition1" x:Shared="False">
|
||||
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ElasticEase Oscillations="1"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
<Storyboard x:Key="Custom2Transition2" x:Shared="False">
|
||||
<DoubleAnimation From="10" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ElasticEase Oscillations="1"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
|
||||
<Storyboard x:Key="Custom3Transition3" x:Shared="False">
|
||||
<DoubleAnimation From=".8" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ElasticEase Oscillations="1"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
|
||||
<cvt:OpcityConvert x:Key="OpcityConvert"/>
|
||||
<cvt:SearchResWidth x:Key="SearchResWidth"/>
|
||||
<temp:SearchIconList x:Key="SearchIconList"/>
|
||||
@@ -74,11 +88,13 @@
|
||||
</ContextMenu>
|
||||
</hc:Card.ContextMenu>
|
||||
<Grid>
|
||||
<StackPanel Panel.ZIndex="1" Margin="0,-10,-300,0" hc:Growl.GrowlParent="True" hc:Growl.Token="MainWindowGrowl"/>
|
||||
<StackPanel Panel.ZIndex="1" Margin="0,-10,-0,0"/>
|
||||
<WrapPanel Orientation="Horizontal" VirtualizingPanel.VirtualizationMode="Recycling"
|
||||
VirtualizingPanel.IsVirtualizing="True"
|
||||
VirtualizingPanel.IsContainerVirtualizable="True"
|
||||
>
|
||||
<UniformGrid x:Name="WrapUFG">
|
||||
<hc:TransitioningContentControl TransitionStoryboard="{StaticResource Custom3Transition3}">
|
||||
<ListBox x:Name="IconListBox" ItemsSource="{Binding AppConfig.SelectedMenuIcons, Mode=OneWay}"
|
||||
BorderThickness="0"
|
||||
Padding="0,10,0,0"
|
||||
@@ -88,11 +104,12 @@
|
||||
</ListBox.Background>
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<DraggAnimatedPanel:DraggAnimatedPanel Background="#00FFFFFF"
|
||||
<!--<DraggAnimatedPanel:DraggAnimatedPanel Background="#00FFFFFF"
|
||||
ItemsWidth="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelWidth, Mode=OneWay}"
|
||||
ItemsHeight="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelHeight, Mode=OneWay}"
|
||||
HorizontalAlignment="Center"
|
||||
SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
|
||||
SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>-->
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
@@ -150,7 +167,8 @@
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
</hc:TransitioningContentControl>
|
||||
</UniformGrid>
|
||||
</WrapPanel>
|
||||
|
||||
</Grid>
|
||||
@@ -172,7 +190,6 @@
|
||||
<SolidColorBrush Color="#FFFFFFFF" Opacity="0"/>
|
||||
</hc:Card.BorderBrush>
|
||||
<Grid>
|
||||
<StackPanel Panel.ZIndex="1" Margin="0,-10,-300,0" hc:Growl.GrowlParent="True" hc:Growl.Token="MainWindowGrowl"/>
|
||||
<WrapPanel Orientation="Horizontal" VirtualizingPanel.VirtualizationMode="Recycling"
|
||||
VirtualizingPanel.IsVirtualizing="True"
|
||||
VirtualizingPanel.IsContainerVirtualizable="True"
|
||||
|
||||
@@ -25,68 +25,75 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
{
|
||||
private AppData appData = MainWindow.appData;
|
||||
|
||||
private volatile static bool DROP_ICON = false;
|
||||
private Thread dropCheckThread = null;
|
||||
ListBoxDragDropManager<IconInfo> dragMgr;
|
||||
|
||||
//private Thread dropCheckThread = null;
|
||||
|
||||
public RightCardControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Loaded += RightCardControl_Loaded;
|
||||
}
|
||||
|
||||
private void RightCardControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.dragMgr = new ListBoxDragDropManager<IconInfo>(this.IconListBox);
|
||||
}
|
||||
|
||||
|
||||
#region 图标拖动
|
||||
DelegateCommand<int[]> _swap;
|
||||
public DelegateCommand<int[]> SwapCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_swap == null)
|
||||
_swap = new DelegateCommand<int[]>(
|
||||
(indexes) =>
|
||||
{
|
||||
DROP_ICON = true;
|
||||
if (appData.AppConfig.IconSortType != SortType.CUSTOM
|
||||
&& (dropCheckThread == null || !dropCheckThread.IsAlive))
|
||||
{
|
||||
dropCheckThread = new Thread(() =>
|
||||
{
|
||||
do
|
||||
{
|
||||
DROP_ICON = false;
|
||||
Thread.Sleep(1000);
|
||||
} while (DROP_ICON);
|
||||
//#region 图标拖动
|
||||
//DelegateCommand<int[]> _swap;
|
||||
//public DelegateCommand<int[]> SwapCommand
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// if (_swap == null)
|
||||
// _swap = new DelegateCommand<int[]>(
|
||||
// (indexes) =>
|
||||
// {
|
||||
// DROP_ICON = true;
|
||||
// if (appData.AppConfig.IconSortType != SortType.CUSTOM
|
||||
// && (dropCheckThread == null || !dropCheckThread.IsAlive))
|
||||
// {
|
||||
// dropCheckThread = new Thread(() =>
|
||||
// {
|
||||
// do
|
||||
// {
|
||||
// DROP_ICON = false;
|
||||
// Thread.Sleep(1000);
|
||||
// } while (DROP_ICON);
|
||||
|
||||
MainWindow.appData.AppConfig.IconSortType = SortType.CUSTOM;
|
||||
App.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (MainWindow.mainWindow.Visibility == Visibility.Collapsed
|
||||
|| MainWindow.mainWindow.Opacity != 1)
|
||||
{
|
||||
Growl.WarningGlobal("已将图标排序规则重置为自定义!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Growl.Warning("已将图标排序规则重置为自定义!", "MainWindowGrowl");
|
||||
}
|
||||
});
|
||||
});
|
||||
dropCheckThread.Start();
|
||||
}
|
||||
int fromS = indexes[0];
|
||||
int to = indexes[1];
|
||||
ObservableCollection<IconInfo> iconList = appData.MenuList[appData.AppConfig.SelectedMenuIndex].IconList;
|
||||
var elementSource = iconList[to];
|
||||
var dragged = iconList[fromS];
|
||||
// MainWindow.appData.AppConfig.IconSortType = SortType.CUSTOM;
|
||||
// App.Current.Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// if (MainWindow.mainWindow.Visibility == Visibility.Collapsed
|
||||
// || MainWindow.mainWindow.Opacity != 1)
|
||||
// {
|
||||
// Growl.WarningGlobal("已将图标排序规则重置为自定义!");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Growl.Warning("已将图标排序规则重置为自定义!", "MainWindowGrowl");
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// dropCheckThread.Start();
|
||||
// }
|
||||
// int fromS = indexes[0];
|
||||
// int to = indexes[1];
|
||||
// ObservableCollection<IconInfo> iconList = appData.MenuList[appData.AppConfig.SelectedMenuIndex].IconList;
|
||||
// var elementSource = iconList[to];
|
||||
// var dragged = iconList[fromS];
|
||||
|
||||
iconList.Remove(dragged);
|
||||
iconList.Insert(to, dragged);
|
||||
}
|
||||
);
|
||||
return _swap;
|
||||
}
|
||||
}
|
||||
// iconList.Remove(dragged);
|
||||
// iconList.Insert(to, dragged);
|
||||
// }
|
||||
// );
|
||||
// return _swap;
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion 图标拖动
|
||||
//#endregion 图标拖动
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -246,11 +246,13 @@
|
||||
<Compile Include="Util\AeroGlassHelper.cs" />
|
||||
<Compile Include="Util\BGSettingUtil.cs" />
|
||||
<Compile Include="Util\ColorUtil.cs" />
|
||||
<Compile Include="Util\DragAdorner.cs" />
|
||||
<Compile Include="Util\GlobalHotKey.cs" />
|
||||
<Compile Include="Util\CommonCode.cs" />
|
||||
<Compile Include="Util\FileIcon.cs" />
|
||||
<Compile Include="Util\FileUtil.cs" />
|
||||
<Compile Include="Util\KeyUtil.cs" />
|
||||
<Compile Include="Util\ListBoxDragDropManager.cs" />
|
||||
<Compile Include="Util\LogUtil.cs" />
|
||||
<Compile Include="Util\MarginHide.cs" />
|
||||
<Compile Include="Util\HttpUtil.cs" />
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
<ColumnDefinition x:Name="RightColumn" Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<StackPanel HorizontalAlignment="Right" Panel.ZIndex="99" hc:Growl.GrowlParent="False" hc:Growl.Token="MainWindowGrowl" Grid.Column="1" Grid.Row="1"/>
|
||||
<!--获取焦点用-->
|
||||
<TextBox x:Name="EmptyTextBox" Width="0"/>
|
||||
|
||||
|
||||
175
Util/DragAdorner.cs
Normal file
175
Util/DragAdorner.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright (C) Josh Smith - January 2007
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders a visual which can follow the mouse cursor,
|
||||
/// such as during a drag-and-drop operation.
|
||||
/// </summary>
|
||||
public class DragAdorner : Adorner
|
||||
{
|
||||
#region Data
|
||||
|
||||
private Rectangle child = null;
|
||||
private double offsetLeft = 0;
|
||||
private double offsetTop = 0;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of DragVisualAdorner.
|
||||
/// </summary>
|
||||
/// <param name="adornedElement">The element being adorned.</param>
|
||||
/// <param name="size">The size of the adorner.</param>
|
||||
/// <param name="brush">A brush to with which to paint the adorner.</param>
|
||||
public DragAdorner( UIElement adornedElement, Size size, Brush brush )
|
||||
: base( adornedElement )
|
||||
{
|
||||
Rectangle rect = new Rectangle();
|
||||
rect.Fill = brush;
|
||||
rect.Width = size.Width;
|
||||
rect.Height = size.Height;
|
||||
rect.IsHitTestVisible = false;
|
||||
this.child = rect;
|
||||
}
|
||||
|
||||
#endregion // Constructor
|
||||
|
||||
#region Public Interface
|
||||
|
||||
#region GetDesiredTransform
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="transform"></param>
|
||||
/// <returns></returns>
|
||||
public override GeneralTransform GetDesiredTransform( GeneralTransform transform )
|
||||
{
|
||||
GeneralTransformGroup result = new GeneralTransformGroup();
|
||||
result.Children.Add( base.GetDesiredTransform( transform ) );
|
||||
result.Children.Add( new TranslateTransform( this.offsetLeft, this.offsetTop ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion // GetDesiredTransform
|
||||
|
||||
#region OffsetLeft
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the horizontal offset of the adorner.
|
||||
/// </summary>
|
||||
public double OffsetLeft
|
||||
{
|
||||
get { return this.offsetLeft; }
|
||||
set
|
||||
{
|
||||
this.offsetLeft = value;
|
||||
UpdateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // OffsetLeft
|
||||
|
||||
#region SetOffsets
|
||||
|
||||
/// <summary>
|
||||
/// Updates the location of the adorner in one atomic operation.
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="top"></param>
|
||||
public void SetOffsets( double left, double top )
|
||||
{
|
||||
this.offsetLeft = left;
|
||||
this.offsetTop = top;
|
||||
this.UpdateLocation();
|
||||
}
|
||||
|
||||
#endregion // SetOffsets
|
||||
|
||||
#region OffsetTop
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the vertical offset of the adorner.
|
||||
/// </summary>
|
||||
public double OffsetTop
|
||||
{
|
||||
get { return this.offsetTop; }
|
||||
set
|
||||
{
|
||||
this.offsetTop = value;
|
||||
UpdateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // OffsetTop
|
||||
|
||||
#endregion // Public Interface
|
||||
|
||||
#region Protected Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="constraint"></param>
|
||||
/// <returns></returns>
|
||||
protected override Size MeasureOverride( Size constraint )
|
||||
{
|
||||
this.child.Measure( constraint );
|
||||
return this.child.DesiredSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="finalSize"></param>
|
||||
/// <returns></returns>
|
||||
protected override Size ArrangeOverride( Size finalSize )
|
||||
{
|
||||
this.child.Arrange( new Rect( finalSize ) );
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
protected override Visual GetVisualChild( int index )
|
||||
{
|
||||
return this.child;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override. Always returns 1.
|
||||
/// </summary>
|
||||
protected override int VisualChildrenCount
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
#endregion // Protected Overrides
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
AdornerLayer adornerLayer = this.Parent as AdornerLayer;
|
||||
if( adornerLayer != null )
|
||||
adornerLayer.Update( this.AdornedElement );
|
||||
}
|
||||
|
||||
#endregion // Private Helpers
|
||||
}
|
||||
}
|
||||
892
Util/ListBoxDragDropManager.cs
Normal file
892
Util/ListBoxDragDropManager.cs
Normal file
@@ -0,0 +1,892 @@
|
||||
// Copyright (C) Josh Smith - January 2007
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Input;
|
||||
using GeekDesk.Util;
|
||||
using GeekDesk.Constant;
|
||||
using HandyControl.Controls;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
#region ListBoxDragDropManager
|
||||
|
||||
/// <summary>
|
||||
/// Manages the dragging and dropping of ListBoxItems in a ListBox.
|
||||
/// The ItemType type parameter indicates the type of the objects in
|
||||
/// the ListBox's items source. The ListBox's ItemsSource must be
|
||||
/// set to an instance of ObservableCollection of ItemType, or an
|
||||
/// Exception will be thrown.
|
||||
/// </summary>
|
||||
/// <typeparam name="ItemType">The type of the ListBox's items.</typeparam>
|
||||
public class ListBoxDragDropManager<ItemType> where ItemType : class
|
||||
{
|
||||
#region Data
|
||||
|
||||
bool canInitiateDrag;
|
||||
DragAdorner dragAdorner;
|
||||
double dragAdornerOpacity;
|
||||
int indexToSelect;
|
||||
bool isDragInProgress;
|
||||
ItemType itemUnderDragCursor;
|
||||
ListBox listBox;
|
||||
Point ptMouseDown;
|
||||
bool showDragAdorner;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListBoxDragManager.
|
||||
/// </summary>
|
||||
public ListBoxDragDropManager()
|
||||
{
|
||||
this.canInitiateDrag = false;
|
||||
this.dragAdornerOpacity = 0.7;
|
||||
this.indexToSelect = -1;
|
||||
this.showDragAdorner = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListBoxDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listBox"></param>
|
||||
public ListBoxDragDropManager( ListBox listBox )
|
||||
: this()
|
||||
{
|
||||
this.ListBox = listBox;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListBoxDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listBox"></param>
|
||||
/// <param name="dragAdornerOpacity"></param>
|
||||
public ListBoxDragDropManager( ListBox listBox, double dragAdornerOpacity )
|
||||
: this( listBox )
|
||||
{
|
||||
this.DragAdornerOpacity = dragAdornerOpacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListBoxDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listBox"></param>
|
||||
/// <param name="showDragAdorner"></param>
|
||||
public ListBoxDragDropManager( ListBox listBox, bool showDragAdorner )
|
||||
: this( listBox )
|
||||
{
|
||||
this.ShowDragAdorner = showDragAdorner;
|
||||
}
|
||||
|
||||
#endregion // Constructors
|
||||
|
||||
#region Public Interface
|
||||
|
||||
#region DragAdornerOpacity
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the opacity of the drag adorner. This property has no
|
||||
/// effect if ShowDragAdorner is false. The default value is 0.7
|
||||
/// </summary>
|
||||
public double DragAdornerOpacity
|
||||
{
|
||||
get { return this.dragAdornerOpacity; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the DragAdornerOpacity property during a drag operation." );
|
||||
|
||||
if( value < 0.0 || value > 1.0 )
|
||||
throw new ArgumentOutOfRangeException( "DragAdornerOpacity", value, "Must be between 0 and 1." );
|
||||
|
||||
this.dragAdornerOpacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // DragAdornerOpacity
|
||||
|
||||
#region IsDragInProgress
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if there is currently a drag operation being managed.
|
||||
/// </summary>
|
||||
public bool IsDragInProgress
|
||||
{
|
||||
get { return this.isDragInProgress; }
|
||||
private set { this.isDragInProgress = value; }
|
||||
}
|
||||
|
||||
#endregion // IsDragInProgress
|
||||
|
||||
#region ListBox
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the ListBox whose dragging is managed. This property
|
||||
/// can be set to null, to prevent drag management from occuring. If
|
||||
/// the ListBox's AllowDrop property is false, it will be set to true.
|
||||
/// </summary>
|
||||
public ListBox ListBox
|
||||
{
|
||||
get { return listBox; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the ListBox property during a drag operation." );
|
||||
|
||||
if( this.listBox != null )
|
||||
{
|
||||
#region Unhook Events
|
||||
|
||||
this.listBox.PreviewMouseLeftButtonDown -= LIstBox_PreviewMouseLeftButtonDown;
|
||||
this.listBox.PreviewMouseMove -= LIstBox_PreviewMouseMove;
|
||||
this.listBox.DragOver -= LIstBox_DragOver;
|
||||
this.listBox.DragLeave -= LIstBox_DragLeave;
|
||||
this.listBox.DragEnter -= LIstBox_DragEnter;
|
||||
this.listBox.Drop -= LIstBox_Drop;
|
||||
|
||||
#endregion // Unhook Events
|
||||
}
|
||||
|
||||
this.listBox = value;
|
||||
|
||||
if( this.listBox != null )
|
||||
{
|
||||
if( !this.listBox.AllowDrop )
|
||||
this.listBox.AllowDrop = true;
|
||||
|
||||
#region Hook Events
|
||||
|
||||
this.listBox.PreviewMouseLeftButtonDown += LIstBox_PreviewMouseLeftButtonDown;
|
||||
this.listBox.PreviewMouseMove += LIstBox_PreviewMouseMove;
|
||||
this.listBox.DragOver += LIstBox_DragOver;
|
||||
this.listBox.DragLeave += LIstBox_DragLeave;
|
||||
this.listBox.DragEnter += LIstBox_DragEnter;
|
||||
this.listBox.Drop += LIstBox_Drop;
|
||||
|
||||
#endregion // Hook Events
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ListBox
|
||||
|
||||
#region ProcessDrop [event]
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a drop occurs. By default the dropped item will be moved
|
||||
/// to the target index. Handle this event if relocating the dropped item
|
||||
/// requires custom behavior. Note, if this event is handled the default
|
||||
/// item dropping logic will not occur.
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessDropEventArgs<ItemType>> ProcessDrop;
|
||||
|
||||
#endregion // ProcessDrop [event]
|
||||
|
||||
#region ShowDragAdorner
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets whether a visual representation of the ListBoxItem being dragged
|
||||
/// follows the mouse cursor during a drag operation. The default value is true.
|
||||
/// </summary>
|
||||
public bool ShowDragAdorner
|
||||
{
|
||||
get { return this.showDragAdorner; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the ShowDragAdorner property during a drag operation." );
|
||||
|
||||
this.showDragAdorner = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ShowDragAdorner
|
||||
|
||||
#endregion // Public Interface
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
#region LIstBox_PreviewMouseLeftButtonDown
|
||||
|
||||
void LIstBox_PreviewMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
|
||||
{
|
||||
if( this.IsMouseOverScrollbar )
|
||||
{
|
||||
// 4/13/2007 - Set the flag to false when cursor is over scrollbar.
|
||||
this.canInitiateDrag = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = this.IndexUnderDragCursor;
|
||||
this.canInitiateDrag = index > -1;
|
||||
|
||||
if( this.canInitiateDrag )
|
||||
{
|
||||
// Remember the location and index of the ListBoxItem the user clicked on for later.
|
||||
this.ptMouseDown = MouseUtil.GetMousePosition();
|
||||
//this.ptMouseDown = MouseUtil.GetMousePosition( this.listBox );
|
||||
this.indexToSelect = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ptMouseDown = new Point( -10000, -10000 );
|
||||
this.indexToSelect = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // LIstBox_PreviewMouseLeftButtonDown
|
||||
|
||||
#region LIstBox_PreviewMouseMove
|
||||
|
||||
void LIstBox_PreviewMouseMove( object sender, MouseEventArgs e )
|
||||
{
|
||||
if( !this.CanStartDragOperation )
|
||||
return;
|
||||
|
||||
// Select the item the user clicked on.
|
||||
if( this.listBox.SelectedIndex != this.indexToSelect )
|
||||
this.listBox.SelectedIndex = this.indexToSelect;
|
||||
|
||||
// If the item at the selected index is null, there's nothing
|
||||
// we can do, so just return;
|
||||
if( this.listBox.SelectedItem == null )
|
||||
return;
|
||||
|
||||
ListBoxItem itemToDrag = this.GetListBoxItem( this.listBox.SelectedIndex );
|
||||
if( itemToDrag == null )
|
||||
return;
|
||||
|
||||
AdornerLayer adornerLayer = this.ShowDragAdornerResolved ? this.InitializeAdornerLayer( itemToDrag ) : null;
|
||||
|
||||
this.InitializeDragOperation( itemToDrag );
|
||||
this.PerformDragOperation();
|
||||
this.FinishDragOperation( itemToDrag, adornerLayer );
|
||||
}
|
||||
|
||||
#endregion // LIstBox_PreviewMouseMove
|
||||
|
||||
#region LIstBox_DragOver
|
||||
|
||||
void LIstBox_DragOver( object sender, DragEventArgs e )
|
||||
{
|
||||
e.Effects = DragDropEffects.Move;
|
||||
|
||||
if ( this.ShowDragAdornerResolved )
|
||||
this.UpdateDragAdornerLocation();
|
||||
|
||||
// Update the item which is known to be currently under the drag cursor.
|
||||
int index = this.IndexUnderDragCursor;
|
||||
this.ItemUnderDragCursor = index < 0 ? null : this.ListBox.Items[index] as ItemType;
|
||||
}
|
||||
|
||||
#endregion // LIstBox_DragOver
|
||||
|
||||
#region LIstBox_DragLeave
|
||||
|
||||
void LIstBox_DragLeave( object sender, DragEventArgs e )
|
||||
{
|
||||
if( !this.IsMouseOver( this.listBox ) )
|
||||
{
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
if( this.dragAdorner != null )
|
||||
this.dragAdorner.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // LIstBox_DragLeave
|
||||
|
||||
#region LIstBox_DragEnter
|
||||
|
||||
void LIstBox_DragEnter( object sender, DragEventArgs e )
|
||||
{
|
||||
if( this.dragAdorner != null && this.dragAdorner.Visibility != Visibility.Visible )
|
||||
{
|
||||
// Update the location of the adorner and then show it.
|
||||
this.UpdateDragAdornerLocation();
|
||||
this.dragAdorner.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // LIstBox_DragEnter
|
||||
|
||||
#region LIstBox_Drop
|
||||
|
||||
void LIstBox_Drop( object sender, DragEventArgs e )
|
||||
{
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
e.Effects = DragDropEffects.None;
|
||||
|
||||
if( !e.Data.GetDataPresent( typeof( ItemType ) ) )
|
||||
return;
|
||||
|
||||
// Get the data object which was dropped.
|
||||
ItemType data = e.Data.GetData( typeof( ItemType ) ) as ItemType;
|
||||
if( data == null )
|
||||
return;
|
||||
|
||||
// Get the ObservableCollection<ItemType> which contains the dropped data object.
|
||||
ObservableCollection<ItemType> itemsSource = this.listBox.ItemsSource as ObservableCollection<ItemType>;
|
||||
if( itemsSource == null )
|
||||
throw new Exception(
|
||||
"A ListBox managed by ListBoxDragManager must have its ItemsSource set to an ObservableCollection<ItemType>." );
|
||||
|
||||
int oldIndex = itemsSource.IndexOf( data );
|
||||
int newIndex = this.IndexUnderDragCursor;
|
||||
|
||||
if( newIndex < 0 )
|
||||
{
|
||||
// The drag started somewhere else, and our ListBox is empty
|
||||
// so make the new item the first in the list.
|
||||
if( itemsSource.Count == 0 )
|
||||
newIndex = 0;
|
||||
|
||||
// The drag started somewhere else, but our ListBox has items
|
||||
// so make the new item the last in the list.
|
||||
else if( oldIndex < 0 )
|
||||
newIndex = itemsSource.Count;
|
||||
|
||||
// The user is trying to drop an item from our ListBox into
|
||||
// our ListBox, but the mouse is not over an item, so don't
|
||||
// let them drop it.
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Dropping an item back onto itself is not considered an actual 'drop'.
|
||||
if( oldIndex == newIndex )
|
||||
return;
|
||||
|
||||
if( this.ProcessDrop != null )
|
||||
{
|
||||
// Let the client code process the drop.
|
||||
ProcessDropEventArgs<ItemType> args = new ProcessDropEventArgs<ItemType>( itemsSource, data, oldIndex, newIndex, e.AllowedEffects );
|
||||
this.ProcessDrop( this, args );
|
||||
e.Effects = args.Effects;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move the dragged data object from it's original index to the
|
||||
// new index (according to where the mouse cursor is). If it was
|
||||
// not previously in the ListBox, then insert the item.
|
||||
if( oldIndex > -1 )
|
||||
{
|
||||
// <20>ⲿҵ<E2B2BF><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
itemsSource.Move(oldIndex, newIndex);
|
||||
if (MainWindow.appData.AppConfig.IconSortType != SortType.CUSTOM)
|
||||
{
|
||||
MainWindow.appData.AppConfig.IconSortType = SortType.CUSTOM;
|
||||
if (MainWindow.mainWindow.Visibility == Visibility.Collapsed
|
||||
|| MainWindow.mainWindow.Opacity != 1)
|
||||
{
|
||||
Growl.WarningGlobal("<22>ѽ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Growl.Warning("<22>ѽ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>!", "MainWindowGrowl");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
itemsSource.Insert(newIndex, data);
|
||||
}
|
||||
|
||||
// Set the Effects property so that the call to DoDragDrop will return 'Move'.
|
||||
e.Effects = DragDropEffects.Move;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // LIstBox_Drop
|
||||
|
||||
#endregion // Event Handling Methods
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
#region CanStartDragOperation
|
||||
|
||||
bool CanStartDragOperation
|
||||
{
|
||||
get
|
||||
{
|
||||
if( Mouse.LeftButton != MouseButtonState.Pressed )
|
||||
return false;
|
||||
|
||||
if( !this.canInitiateDrag )
|
||||
return false;
|
||||
|
||||
if( this.indexToSelect == -1 )
|
||||
return false;
|
||||
|
||||
if( !this.HasCursorLeftDragThreshold )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // CanStartDragOperation
|
||||
|
||||
#region FinishDragOperation
|
||||
|
||||
void FinishDragOperation( ListBoxItem draggedItem, AdornerLayer adornerLayer )
|
||||
{
|
||||
// Let the ListBoxItem know that it is not being dragged anymore.
|
||||
ListBoxItemDragState.SetIsBeingDragged( draggedItem, false );
|
||||
|
||||
this.IsDragInProgress = false;
|
||||
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
// Remove the drag adorner from the adorner layer.
|
||||
if( adornerLayer != null )
|
||||
{
|
||||
adornerLayer.Remove( this.dragAdorner );
|
||||
this.dragAdorner = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // FinishDragOperation
|
||||
|
||||
#region GetListBoxItem
|
||||
|
||||
ListBoxItem GetListBoxItem( int index )
|
||||
{
|
||||
if( this.listBox.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||
return null;
|
||||
|
||||
return this.listBox.ItemContainerGenerator.ContainerFromIndex( index ) as ListBoxItem;
|
||||
}
|
||||
|
||||
ListBoxItem GetListBoxItem( ItemType dataItem )
|
||||
{
|
||||
if( this.listBox.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||
return null;
|
||||
|
||||
return this.listBox.ItemContainerGenerator.ContainerFromItem( dataItem ) as ListBoxItem;
|
||||
}
|
||||
|
||||
#endregion // GetListBoxItem
|
||||
|
||||
#region HasCursorLeftDragThreshold
|
||||
|
||||
bool HasCursorLeftDragThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
if( this.indexToSelect < 0 )
|
||||
return false;
|
||||
|
||||
ListBoxItem item = this.GetListBoxItem( this.indexToSelect );
|
||||
Rect bounds = VisualTreeHelper.GetDescendantBounds( item );
|
||||
Point ptInItem = this.listBox.TranslatePoint( this.ptMouseDown, item );
|
||||
|
||||
// In case the cursor is at the very top or bottom of the ListBoxItem
|
||||
// we want to make the vertical threshold very small so that dragging
|
||||
// over an adjacent item does not select it.
|
||||
double topOffset = Math.Abs( ptInItem.Y );
|
||||
double btmOffset = Math.Abs( bounds.Height - ptInItem.Y );
|
||||
double vertOffset = Math.Min( topOffset, btmOffset );
|
||||
|
||||
double width = SystemParameters.MinimumHorizontalDragDistance * 2;
|
||||
double height = Math.Min( SystemParameters.MinimumVerticalDragDistance, vertOffset ) * 2;
|
||||
Size szThreshold = new Size( width, height );
|
||||
|
||||
Rect rect = new Rect( this.ptMouseDown, szThreshold );
|
||||
rect.Offset( szThreshold.Width / -2, szThreshold.Height / -2 );
|
||||
//Point ptInListBox = MouseUtil.GetMousePosition(this.listBox);
|
||||
Point ptInListBox = MouseUtil.GetMousePosition();
|
||||
return !rect.Contains( ptInListBox );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // HasCursorLeftDragThreshold
|
||||
|
||||
#region IndexUnderDragCursor
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the ListBoxItem underneath the
|
||||
/// drag cursor, or -1 if the cursor is not over an item.
|
||||
/// </summary>
|
||||
int IndexUnderDragCursor
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = -1;
|
||||
for( int i = 0; i < this.listBox.Items.Count; ++i )
|
||||
{
|
||||
ListBoxItem item = this.GetListBoxItem( i );
|
||||
if( this.IsMouseOver( item ) )
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // IndexUnderDragCursor
|
||||
|
||||
#region InitializeAdornerLayer
|
||||
|
||||
AdornerLayer InitializeAdornerLayer( ListBoxItem itemToDrag )
|
||||
{
|
||||
// Create a brush which will paint the ListBoxItem onto
|
||||
// a visual in the adorner layer.
|
||||
VisualBrush brush = new VisualBrush( itemToDrag );
|
||||
|
||||
// Create an element which displays the source item while it is dragged.
|
||||
this.dragAdorner = new DragAdorner( this.listBox, itemToDrag.RenderSize, brush );
|
||||
|
||||
// Set the drag adorner's opacity.
|
||||
this.dragAdorner.Opacity = this.DragAdornerOpacity;
|
||||
|
||||
AdornerLayer layer = AdornerLayer.GetAdornerLayer( this.listBox );
|
||||
layer.Add( dragAdorner );
|
||||
|
||||
// Save the location of the cursor when the left mouse button was pressed.
|
||||
this.ptMouseDown = MouseUtil.GetMousePosition(this.listBox);
|
||||
//this.ptMouseDown = MouseUtil.GetMousePosition();
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
#endregion // InitializeAdornerLayer
|
||||
|
||||
#region InitializeDragOperation
|
||||
|
||||
void InitializeDragOperation( ListBoxItem itemToDrag )
|
||||
{
|
||||
// Set some flags used during the drag operation.
|
||||
this.IsDragInProgress = true;
|
||||
this.canInitiateDrag = false;
|
||||
|
||||
// Let the ListBoxItem know that it is being dragged.
|
||||
ListBoxItemDragState.SetIsBeingDragged( itemToDrag, true );
|
||||
}
|
||||
|
||||
#endregion // InitializeDragOperation
|
||||
|
||||
#region IsMouseOver
|
||||
|
||||
bool IsMouseOver( Visual target )
|
||||
{
|
||||
// We need to use MouseUtil to figure out the cursor
|
||||
// coordinates because, during a drag-drop operation, the WPF
|
||||
// mechanisms for getting the coordinates behave strangely.
|
||||
|
||||
Rect bounds = VisualTreeHelper.GetDescendantBounds( target );
|
||||
Point mousePos = MouseUtil.GetMousePosition( target );
|
||||
return bounds.Contains( mousePos );
|
||||
}
|
||||
|
||||
#endregion // IsMouseOver
|
||||
|
||||
#region IsMouseOverScrollbar
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the mouse cursor is over a scrollbar in the ListBox.
|
||||
/// </summary>
|
||||
bool IsMouseOverScrollbar
|
||||
{
|
||||
get
|
||||
{
|
||||
Point ptMouse = MouseUtil.GetMousePosition( this.listBox );
|
||||
HitTestResult res = VisualTreeHelper.HitTest( this.listBox, ptMouse );
|
||||
if( res == null )
|
||||
return false;
|
||||
|
||||
DependencyObject depObj = res.VisualHit;
|
||||
while( depObj != null )
|
||||
{
|
||||
if( depObj is ScrollBar )
|
||||
return true;
|
||||
|
||||
// VisualTreeHelper works with objects of type Visual or Visual3D.
|
||||
// If the current object is not derived from Visual or Visual3D,
|
||||
// then use the LogicalTreeHelper to find the parent element.
|
||||
if( depObj is Visual || depObj is System.Windows.Media.Media3D.Visual3D )
|
||||
depObj = VisualTreeHelper.GetParent( depObj );
|
||||
else
|
||||
depObj = LogicalTreeHelper.GetParent( depObj );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // IsMouseOverScrollbar
|
||||
|
||||
#region ItemUnderDragCursor
|
||||
|
||||
ItemType ItemUnderDragCursor
|
||||
{
|
||||
get { return this.itemUnderDragCursor; }
|
||||
set
|
||||
{
|
||||
if( this.itemUnderDragCursor == value )
|
||||
return;
|
||||
|
||||
// The first pass handles the previous item under the cursor.
|
||||
// The second pass handles the new one.
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
if( i == 1 )
|
||||
this.itemUnderDragCursor = value;
|
||||
|
||||
if( this.itemUnderDragCursor != null )
|
||||
{
|
||||
ListBoxItem listBoxItem = this.GetListBoxItem( this.itemUnderDragCursor );
|
||||
if( listBoxItem != null )
|
||||
ListBoxItemDragState.SetIsUnderDragCursor( listBoxItem, i == 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ItemUnderDragCursor
|
||||
|
||||
#region PerformDragOperation
|
||||
|
||||
void PerformDragOperation()
|
||||
{
|
||||
ItemType selectedItem = this.listBox.SelectedItem as ItemType;
|
||||
DragDropEffects allowedEffects = DragDropEffects.Move | DragDropEffects.Move | DragDropEffects.Link;
|
||||
if( DragDrop.DoDragDrop( this.listBox, selectedItem, allowedEffects ) != DragDropEffects.None )
|
||||
{
|
||||
// The item was dropped into a new location,
|
||||
// so make it the new selected item.
|
||||
this.listBox.SelectedItem = selectedItem;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // PerformDragOperation
|
||||
|
||||
#region ShowDragAdornerResolved
|
||||
|
||||
bool ShowDragAdornerResolved
|
||||
{
|
||||
get { return this.ShowDragAdorner && this.DragAdornerOpacity > 0.0; }
|
||||
}
|
||||
|
||||
#endregion // ShowDragAdornerResolved
|
||||
|
||||
#region UpdateDragAdornerLocation
|
||||
|
||||
void UpdateDragAdornerLocation()
|
||||
{
|
||||
if( this.dragAdorner != null )
|
||||
{
|
||||
//Point ptCursor = MouseUtil.GetMousePosition(this.ListBox);
|
||||
|
||||
|
||||
Point ptCursor = MouseUtil.GetMousePosition(this.ListBox);
|
||||
|
||||
//double left = ptCursor.X - this.ptMouseDown.X;
|
||||
//double left2 = ptCursor.X;
|
||||
|
||||
ListBoxItem itemBeingDragged = this.GetListBoxItem(this.indexToSelect);
|
||||
|
||||
// 4/13/2007 - Made the top offset relative to the item being dragged.
|
||||
Point itemLoc = itemBeingDragged.TranslatePoint( new Point( 0, 0 ), this.ListBox );
|
||||
double top = itemLoc.Y + ptCursor.Y - this.ptMouseDown.Y;
|
||||
double left = itemLoc.X + ptCursor.X - this.ptMouseDown.X;
|
||||
|
||||
this.dragAdorner.SetOffsets(left, top );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // UpdateDragAdornerLocation
|
||||
|
||||
#endregion // Private Helpers
|
||||
}
|
||||
|
||||
#endregion // ListBoxDragDropManager
|
||||
|
||||
#region ListBoxItemDragState
|
||||
|
||||
/// <summary>
|
||||
/// Exposes attached properties used in conjunction with the ListBoxDragDropManager class.
|
||||
/// Those properties can be used to allow triggers to modify the appearance of ListBoxItems
|
||||
/// in a ListBox during a drag-drop operation.
|
||||
/// </summary>
|
||||
public static class ListBoxItemDragState
|
||||
{
|
||||
#region IsBeingDragged
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the ListBoxItemDragState's IsBeingDragged attached property.
|
||||
/// This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsBeingDraggedProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsBeingDragged",
|
||||
typeof( bool ),
|
||||
typeof( ListBoxItemDragState ),
|
||||
new UIPropertyMetadata( false ) );
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified ListBoxItem is being dragged, else false.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListBoxItem to check.</param>
|
||||
public static bool GetIsBeingDragged( ListBoxItem item )
|
||||
{
|
||||
return (bool)item.GetValue( IsBeingDraggedProperty );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the IsBeingDragged attached property for the specified ListBoxItem.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListBoxItem to set the property on.</param>
|
||||
/// <param name="value">Pass true if the element is being dragged, else false.</param>
|
||||
internal static void SetIsBeingDragged( ListBoxItem item, bool value )
|
||||
{
|
||||
item.SetValue( IsBeingDraggedProperty, value );
|
||||
}
|
||||
|
||||
#endregion // IsBeingDragged
|
||||
|
||||
#region IsUnderDragCursor
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the ListBoxItemDragState's IsUnderDragCursor attached property.
|
||||
/// This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsUnderDragCursorProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsUnderDragCursor",
|
||||
typeof( bool ),
|
||||
typeof( ListBoxItemDragState ),
|
||||
new UIPropertyMetadata( false ) );
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified ListBoxItem is currently underneath the cursor
|
||||
/// during a drag-drop operation, else false.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListBoxItem to check.</param>
|
||||
public static bool GetIsUnderDragCursor( ListBoxItem item )
|
||||
{
|
||||
return (bool)item.GetValue( IsUnderDragCursorProperty );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the IsUnderDragCursor attached property for the specified ListBoxItem.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListBoxItem to set the property on.</param>
|
||||
/// <param name="value">Pass true if the element is underneath the drag cursor, else false.</param>
|
||||
internal static void SetIsUnderDragCursor( ListBoxItem item, bool value )
|
||||
{
|
||||
item.SetValue( IsUnderDragCursorProperty, value );
|
||||
}
|
||||
|
||||
#endregion // IsUnderDragCursor
|
||||
}
|
||||
|
||||
#endregion // ListBoxItemDragState
|
||||
|
||||
#region ProcessDropEventArgs
|
||||
|
||||
/// <summary>
|
||||
/// Event arguments used by the ListBoxDragDropManager.ProcessDrop event.
|
||||
/// </summary>
|
||||
/// <typeparam name="ItemType">The type of data object being dropped.</typeparam>
|
||||
public class ProcessDropEventArgs<ItemType> : EventArgs where ItemType : class
|
||||
{
|
||||
#region Data
|
||||
|
||||
ObservableCollection<ItemType> itemsSource;
|
||||
ItemType dataItem;
|
||||
int oldIndex;
|
||||
int newIndex;
|
||||
DragDropEffects allowedEffects = DragDropEffects.None;
|
||||
DragDropEffects effects = DragDropEffects.None;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructor
|
||||
|
||||
internal ProcessDropEventArgs(
|
||||
ObservableCollection<ItemType> itemsSource,
|
||||
ItemType dataItem,
|
||||
int oldIndex,
|
||||
int newIndex,
|
||||
DragDropEffects allowedEffects )
|
||||
{
|
||||
this.itemsSource = itemsSource;
|
||||
this.dataItem = dataItem;
|
||||
this.oldIndex = oldIndex;
|
||||
this.newIndex = newIndex;
|
||||
this.allowedEffects = allowedEffects;
|
||||
}
|
||||
|
||||
#endregion // Constructor
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// The items source of the ListBox where the drop occurred.
|
||||
/// </summary>
|
||||
public ObservableCollection<ItemType> ItemsSource
|
||||
{
|
||||
get { return this.itemsSource; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data object which was dropped.
|
||||
/// </summary>
|
||||
public ItemType DataItem
|
||||
{
|
||||
get { return this.dataItem; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current index of the data item being dropped, in the ItemsSource collection.
|
||||
/// </summary>
|
||||
public int OldIndex
|
||||
{
|
||||
get { return this.oldIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target index of the data item being dropped, in the ItemsSource collection.
|
||||
/// </summary>
|
||||
public int NewIndex
|
||||
{
|
||||
get { return this.newIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The drag drop effects allowed to be performed.
|
||||
/// </summary>
|
||||
public DragDropEffects AllowedEffects
|
||||
{
|
||||
get { return allowedEffects; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The drag drop effect(s) performed on the dropped item.
|
||||
/// </summary>
|
||||
public DragDropEffects Effects
|
||||
{
|
||||
get { return effects; }
|
||||
set { effects = value; }
|
||||
}
|
||||
|
||||
#endregion // Public Properties
|
||||
}
|
||||
|
||||
#endregion // ProcessDropEventArgs
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
@@ -27,5 +28,27 @@ namespace GeekDesk.Util
|
||||
GetCursorPos(ref w32Mouse);
|
||||
return new Point(w32Mouse.X, w32Mouse.Y);
|
||||
}
|
||||
|
||||
|
||||
public static Point GetMousePosition(Visual relativeTo)
|
||||
{
|
||||
Win32Point mouse = new Win32Point();
|
||||
GetCursorPos(ref mouse);
|
||||
|
||||
// Using PointFromScreen instead of Dan Crevier's code (commented out below)
|
||||
// is a bug fix created by William J. Roberts. Read his comments about the fix
|
||||
// here: http://www.codeproject.com/useritems/ListViewDragDropManager.asp?msg=1911611#xx1911611xx
|
||||
return relativeTo.PointFromScreen(new Point((double)mouse.X, (double)mouse.Y));
|
||||
|
||||
#region Commented Out
|
||||
//System.Windows.Interop.HwndSource presentationSource =
|
||||
// (System.Windows.Interop.HwndSource)PresentationSource.FromVisual( relativeTo );
|
||||
//ScreenToClient( presentationSource.Handle, ref mouse );
|
||||
//GeneralTransform transform = relativeTo.TransformToAncestor( presentationSource.RootVisual );
|
||||
//Point offset = transform.Transform( new Point( 0, 0 ) );
|
||||
//return new Point( mouse.X - offset.X, mouse.Y - offset.Y );
|
||||
#endregion // Commented Out
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user