瀏覽代碼

:sparkles: 增加可拖动到其它菜单功能 :zap: 切换了icon动画

liufei 3 年之前
父節點
當前提交
b47dd0fbf7

+ 139 - 94
Control/UserControls/PannelCard/LeftCardControl.xaml

@@ -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,110 +77,149 @@
                     <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>
-    <!--左侧栏-->
-    <hc:Card x:Name="MyCard"
-             BorderThickness="1"
-             Effect="{DynamicResource EffectShadow2}" 
-             Margin="5,0,0,5"
-             MouseDown="MyCard_MouseDown"
-             >
-        <hc:Card.Background>
-            <SolidColorBrush Color="#FFFFFFFF" hc:GeometryEffect.GeometryEffect="20" Opacity="{Binding AppConfig.CardOpacity, Mode=TwoWay, Converter={StaticResource OpcityConvert}}">
-
-            </SolidColorBrush>
-        </hc:Card.Background>
-        <hc:Card.BorderBrush>
-            <SolidColorBrush Color="#FFFFFFFF" Opacity="0"/>
-        </hc:Card.BorderBrush>
-        <hc:Card.ContextMenu>
-            <ContextMenu Width="200">
-                <MenuItem Header="新建菜单" Click="CreateMenu"/>
-            </ContextMenu>
-        </hc:Card.ContextMenu>
-        <WrapPanel Orientation="Horizontal">
-            <ListBox x:Name="MenuListBox"
-                     Padding="2,3,0,2"
-                     ItemsSource="{Binding MenuList}"
-                     Tag="{Binding AppConfig.MenuCardWidth}"
-                     BorderThickness="0" Foreground="{x:Null}"
-                     SelectedIndex="{Binding AppConfig.SelectedMenuIndex}"
-                     VirtualizingPanel.VirtualizationMode="Recycling"
-                     SelectionChanged="Menu_SelectionChanged"
-                     PreviewMouseWheel="Menu_MouseWheel"
-                     >
-                <ListBox.Resources>
-                    <ContextMenu x:Key="MenuDialog" Width="200">
-                        <MenuItem Header="新建菜单" Click="CreateMenu"/>
-                        <MenuItem Header="重命名"  Click="RenameMenu" Tag="{Binding}"/>
-                        <MenuItem Header="修改图标"  Click="EditMenuGeometry" Tag="{Binding}"/>
-                        <MenuItem Header="删除" Click="DeleteMenu" Tag="{Binding}"/>
-                    </ContextMenu>
-                </ListBox.Resources>
-
-                <ListBox.ItemContainerStyle>
-                    <Style TargetType="ListBoxItem" BasedOn="{StaticResource MenuStyle}">
-                        <Setter Property="ContextMenu" Value="{StaticResource MenuDialog}"/>
-                    </Style>
-                </ListBox.ItemContainerStyle>
-                <ListBox.Background>
-                    <SolidColorBrush Color="AliceBlue" Opacity="0"/>
-                </ListBox.Background>
-
-                <ListBox.ItemsPanel>
-                    <ItemsPanelTemplate>
-                        <DraggAnimatedPanel:DraggAnimatedPanel ItemsHeight="33" ItemsWidth="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBox},AncestorLevel=1},Path=Tag, Mode=TwoWay, Converter={StaticResource MenuWidthConvert}, ConverterParameter=10}"   HorizontalAlignment="Center" VerticalAlignment="Top" SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
-                    </ItemsPanelTemplate>
-                </ListBox.ItemsPanel>
-
-                <ListBox.ItemTemplate>
-                    <DataTemplate>
-                        <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}"
-                                    FontSize="16"
-                                    Height="28"
-                                    VerticalAlignment="Center"
-                                    TextAlignment="Left"
-                                    LostFocus="LostFocusOrEnterDown"
-                                    KeyDown="LostFocusOrEnterDown"
-                                    Tag="{Binding}"
-                                    Padding="2"
+    <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"
+            Effect="{DynamicResource EffectShadow2}" 
+            Margin="5,0,0,5"
+            MouseDown="MyCard_MouseDown"
+            >
+            <hc:Card.Background>
+                <SolidColorBrush Color="#FFFFFFFF" hc:GeometryEffect.GeometryEffect="20" Opacity="{Binding AppConfig.CardOpacity, Mode=TwoWay, Converter={StaticResource OpcityConvert}}">
+
+                </SolidColorBrush>
+            </hc:Card.Background>
+            <hc:Card.BorderBrush>
+                <SolidColorBrush Color="#FFFFFFFF" Opacity="0"/>
+            </hc:Card.BorderBrush>
+            <hc:Card.ContextMenu>
+                <ContextMenu Width="200">
+                    <MenuItem Header="新建菜单" Click="CreateMenu"/>
+                </ContextMenu>
+            </hc:Card.ContextMenu>
+
+            <WrapPanel Orientation="Horizontal">
+
+
+
+
+                <ListBox x:Name="MenuListBox"
+                    Padding="2,3,0,2"
+                    ItemsSource="{Binding MenuList}"
+                    Tag="{Binding AppConfig.MenuCardWidth}"
+                    BorderThickness="0" Foreground="{x:Null}"
+                    SelectedIndex="{Binding AppConfig.SelectedMenuIndex}"
+                    VirtualizingPanel.VirtualizationMode="Recycling"
+                    SelectionChanged="Menu_SelectionChanged"
+                    PreviewMouseWheel="Menu_MouseWheel"
+                    >
+                    <ListBox.Resources>
+                        <ContextMenu x:Key="MenuDialog" Width="200">
+                            <MenuItem Header="新建菜单" Click="CreateMenu"/>
+                            <MenuItem Header="重命名"  Click="RenameMenu" Tag="{Binding}"/>
+                            <MenuItem Header="修改图标"  Click="EditMenuGeometry" Tag="{Binding}"/>
+                            <MenuItem Header="删除" Click="DeleteMenu" Tag="{Binding}"/>
+                        </ContextMenu>
+                    </ListBox.Resources>
+
+                    <ListBox.ItemContainerStyle>
+                        <Style TargetType="ListBoxItem" BasedOn="{StaticResource MenuStyle}">
+                            <Setter Property="ContextMenu" Value="{StaticResource MenuDialog}"/>
+                        </Style>
+                    </ListBox.ItemContainerStyle>
+                    <ListBox.Background>
+                        <SolidColorBrush Color="AliceBlue" Opacity="0"/>
+                    </ListBox.Background>
+
+                    <ListBox.ItemsPanel>
+                        <ItemsPanelTemplate>
+                            <DraggAnimatedPanel:DraggAnimatedPanel ItemsHeight="33" ItemsWidth="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBox},AncestorLevel=1},Path=Tag, Mode=TwoWay, Converter={StaticResource MenuWidthConvert}, ConverterParameter=10}"   HorizontalAlignment="Center" VerticalAlignment="Top" SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
+                        </ItemsPanelTemplate>
+                    </ListBox.ItemsPanel>
+
+                    <ListBox.ItemTemplate>
+                        <DataTemplate>
+                            <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}"
+                                FontSize="16"
+                                Height="28"
+                                VerticalAlignment="Center"
+                                TextAlignment="Left"
+                                LostFocus="LostFocusOrEnterDown"
+                                KeyDown="LostFocusOrEnterDown"
+                                Tag="{Binding}"
+                                Padding="2"
+                                BorderThickness="0"
+                                IsVisibleChanged="MenuEditWhenVisibilityChanged"
+                                Visibility="{Binding MenuEdit}"/>
+                                <StackPanel Orientation="Horizontal"
+                                IsVisibleChanged="MenuWhenVisibilityChanged"
+                                Visibility="{Binding NotMenuEdit}">
+                                    <Button Background="Transparent" 
                                     BorderThickness="0"
-                                    IsVisibleChanged="MenuEditWhenVisibilityChanged"
-                                    Visibility="{Binding MenuEdit}"/>
-                            <StackPanel Orientation="Horizontal"
-                                    IsVisibleChanged="MenuWhenVisibilityChanged"
-                                    Visibility="{Binding NotMenuEdit}">
-                                <Button Background="Transparent" 
-                                        BorderThickness="0"
-                                        hc:IconElement.Geometry="{Binding MenuGeometry}"
-                                        hc:IconElement.Height="18"
-                                        hc:IconElement.Width="18"
-                                        IsEnabled="False"
-                                        Opacity="1"
-                                        Foreground="{Binding GeometryColor}"
+                                    hc:IconElement.Geometry="{Binding MenuGeometry}"
+                                    hc:IconElement.Height="18"
+                                    hc:IconElement.Width="18"
+                                    IsEnabled="False"
+                                    Opacity="1"
+                                    Foreground="{Binding GeometryColor}"
+                                    />
+                                    <TextBlock Text="{Binding MenuName}"
+                                        HorizontalAlignment="Center"
+                                        TextAlignment="Center"
+                                        VerticalAlignment="Center"
                                         />
-                                <TextBlock Text="{Binding MenuName}"
-                                           HorizontalAlignment="Center"
-                                           TextAlignment="Center"
-                                           VerticalAlignment="Center"
-                                            />
+                                </StackPanel>
                             </StackPanel>
-                        </StackPanel>
-                    </DataTemplate>
-                </ListBox.ItemTemplate>
-            </ListBox>
-        </WrapPanel>
-    </hc:Card>
+                        </DataTemplate>
+                    </ListBox.ItemTemplate>
+                </ListBox>
+            </WrapPanel>
+        </hc:Card>
+    </Grid>
 </UserControl>

+ 34 - 0
Control/UserControls/PannelCard/LeftCardControl.xaml.cs

@@ -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);
+        }
     }
 }

+ 64 - 47
Control/UserControls/PannelCard/RightCardControl.xaml

@@ -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,49 +88,52 @@
                 </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"
                    >
-                    <ListBox x:Name="IconListBox" ItemsSource="{Binding AppConfig.SelectedMenuIcons, Mode=OneWay}" 
+                    <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"
                                  >
-                        <ListBox.Background>
-                            <SolidColorBrush Opacity="0"/>
-                        </ListBox.Background>
-                        <ListBox.ItemsPanel>
-                            <ItemsPanelTemplate>
-                                <DraggAnimatedPanel:DraggAnimatedPanel Background="#00FFFFFF"
+                                <ListBox.Background>
+                                    <SolidColorBrush Opacity="0"/>
+                                </ListBox.Background>
+                                <ListBox.ItemsPanel>
+                                    <ItemsPanelTemplate>
+                                        <!--<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}}}"/>
-                            </ItemsPanelTemplate>
-                        </ListBox.ItemsPanel>
+                                                               SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>-->
+                                        <WrapPanel />
+                                    </ItemsPanelTemplate>
+                                </ListBox.ItemsPanel>
 
-                        <ListBox.Resources>
-                            <ContextMenu x:Key="IconDialog" Width="200">
-                                <MenuItem Header="管理员方式运行" Click="IconAdminStart" Tag="{Binding}"/>
-                                <MenuItem Header="打开文件所在位置" Click="ShowInExplore" Tag="{Binding}"/>
-                                <MenuItem Header="添加URL项目" Click="AddUrlIcon"/>
-                                <MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
-                                <MenuItem Header="资源管理器菜单" Click="SystemContextMenu" Tag="{Binding}"/>
-                                <MenuItem Header="属性" Click="PropertyConfig" Tag="{Binding}"/>
-                                <MenuItem Header="从列表移除" Click="RemoveIcon" Tag="{Binding}"/>
-                            </ContextMenu>
-                        </ListBox.Resources>
+                                <ListBox.Resources>
+                                    <ContextMenu x:Key="IconDialog" Width="200">
+                                        <MenuItem Header="管理员方式运行" Click="IconAdminStart" Tag="{Binding}"/>
+                                        <MenuItem Header="打开文件所在位置" Click="ShowInExplore" Tag="{Binding}"/>
+                                        <MenuItem Header="添加URL项目" Click="AddUrlIcon"/>
+                                        <MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
+                                        <MenuItem Header="资源管理器菜单" Click="SystemContextMenu" Tag="{Binding}"/>
+                                        <MenuItem Header="属性" Click="PropertyConfig" Tag="{Binding}"/>
+                                        <MenuItem Header="从列表移除" Click="RemoveIcon" Tag="{Binding}"/>
+                                    </ContextMenu>
+                                </ListBox.Resources>
 
-                        <ListBox.ItemContainerStyle>
-                            <Style TargetType="ListBoxItem" BasedOn="{StaticResource MyListBoxItemStyle}">
-                                <Setter Property="ContextMenu" Value="{StaticResource IconDialog}"/>
-                            </Style>
-                        </ListBox.ItemContainerStyle>
+                                <ListBox.ItemContainerStyle>
+                                    <Style TargetType="ListBoxItem" BasedOn="{StaticResource MyListBoxItemStyle}">
+                                        <Setter Property="ContextMenu" Value="{StaticResource IconDialog}"/>
+                                    </Style>
+                                </ListBox.ItemContainerStyle>
 
-                        <ListBox.ItemTemplate>
-                            <DataTemplate>
-                                <hc:SimpleStackPanel Tag="{Binding}"
+                                <ListBox.ItemTemplate>
+                                    <DataTemplate>
+                                        <hc:SimpleStackPanel Tag="{Binding}"
                                                      Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelHeight, Mode=OneWay}" 
                                                      Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelWidth, Mode=OneWay}"
                                                      HorizontalAlignment="Center"
@@ -128,7 +145,7 @@
                                                      MouseLeftButtonDown="Icon_MouseLeftButtonDown"
                                                      MouseLeftButtonUp="Icon_MouseLeftButtonUp"
                                                      >
-                                    <!--<StackPanel Background="#00FFFFFF"
+                                            <!--<StackPanel Background="#00FFFFFF"
                                                 MouseEnter="CursorPanel_MouseEnter"
                                                 MouseLeave="CursorPanel_MouseLeave"
                                                 Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageWidth, Mode=OneWay}">-->
@@ -144,13 +161,14 @@
                                                        VerticalAlignment="Center" 
                                                        Foreground="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.TextColor}"
                                                        Text="{Binding Name}"/>
-                                    <!--</StackPanel>-->
-                                    
-                                </hc:SimpleStackPanel>
-                            </DataTemplate>
-                        </ListBox.ItemTemplate>
-                    </ListBox>
+                                            <!--</StackPanel>-->
 
+                                        </hc:SimpleStackPanel>
+                                    </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"

+ 60 - 53
Control/UserControls/PannelCard/RightCardControl.xaml.cs

@@ -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;
         }
 
-
-        #region 图标拖动
-        DelegateCommand<int[]> _swap;
-        public DelegateCommand<int[]> SwapCommand
+        private void RightCardControl_Loaded(object sender, RoutedEventArgs e)
         {
-            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];
-
-                            iconList.Remove(dragged);
-                            iconList.Insert(to, dragged);
-                        }
-                    );
-                return _swap;
-            }
+            this.dragMgr = new ListBoxDragDropManager<IconInfo>(this.IconListBox);
         }
 
-        #endregion 图标拖动
+
+        //#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];
+
+        //                    iconList.Remove(dragged);
+        //                    iconList.Insert(to, dragged);
+        //                }
+        //            );
+        //        return _swap;
+        //    }
+        //}
+
+        //#endregion 图标拖动
 
 
 

+ 2 - 0
GeekDesk.csproj

@@ -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" />

+ 3 - 1
MainWindow.xaml

@@ -37,7 +37,7 @@
         <cvt:IntToCornerRadius x:Key="IntToCornerRadius"/>
         <cvt:DoubleToGridLength x:Key="DoubleToGridLength"/>
         <Style x:Key="BorderBacStyle" TargetType="Border">
-            
+
         </Style>
 
     </Window.Resources>
@@ -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 - 0
Util/DragAdorner.cs

@@ -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 - 0
Util/ListBoxDragDropManager.cs

@@ -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 )
+                {
+					// 外部业务代码
+					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("已将图标排序规则重置为自定义!");
+						}
+						else
+						{
+							Growl.Warning("已将图标排序规则重置为自定义!", "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
+}

+ 23 - 0
Util/MouseUtil.cs

@@ -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
+        }
+
     }
 }