添加项目文件。
This commit is contained in:
14
App.config
Normal file
14
App.config
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="CommonServiceLocator" publicKeyToken="489b6accfaf20ef0" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.0.6.0" newVersion="2.0.6.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
||||||
17
App.xaml
Normal file
17
App.xaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Application x:Class="GeekDesk.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:GeekDesk"
|
||||||
|
StartupUri="MainWindow.xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
d1p1:Ignorable="d"
|
||||||
|
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
17
App.xaml.cs
Normal file
17
App.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace GeekDesk
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// App.xaml 的交互逻辑
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
127
Command/DelegateCommand.cs
Normal file
127
Command/DelegateCommand.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// Developed by doiTTeam => devdoiTTeam@gmail.com
|
||||||
|
using System;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace DraggAnimatedPanelExample
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref = "ICommand" /> whose delegates can be attached for <see cref = "Execute" /> and <see cref = "CanExecute" />.
|
||||||
|
/// It also implements the <see cref = "IActiveAware" /> interface, which is useful when registering this command in a <see cref = "CompositeCommand" /> that monitors command's activity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name = "T">Parameter type.</typeparam>
|
||||||
|
/// <remarks>
|
||||||
|
/// The constructor deliberately prevent the use of value types.
|
||||||
|
/// Because ICommand takes an object, having a value type for T would cause unexpected behavior when CanExecute(null) is called during XAML initialization for command bindings.
|
||||||
|
/// Using default(T) was considered and rejected as a solution because the implementor would not be able to distinguish between a valid and defaulted values.
|
||||||
|
/// <para />
|
||||||
|
/// Instead, callers should support a value type by using a nullable value type and checking the HasValue property before using the Value property.
|
||||||
|
/// <example>
|
||||||
|
/// <code>
|
||||||
|
/// public MyClass()
|
||||||
|
/// {
|
||||||
|
/// this.submitCommand = new DelegateCommand<int?>(this.Submit, this.CanSubmit);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// private bool CanSubmit(int? customerId)
|
||||||
|
/// {
|
||||||
|
/// return (customerId.HasValue && customers.Contains(customerId.Value));
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
/// </remarks>
|
||||||
|
public class DelegateCommand<T> : DelegateCommandBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref = "DelegateCommand{T}" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "executeMethod">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// <seealso cref = "CanExecute" /> will always return true.
|
||||||
|
/// </remarks>
|
||||||
|
public DelegateCommand(Action<T> executeMethod)
|
||||||
|
: this(executeMethod, (o) => true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref = "DelegateCommand{T}" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "executeMethod">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
|
||||||
|
/// <param name = "canExecuteMethod">Delegate to execute when CanExecute is called on the command. This can be null.</param>
|
||||||
|
/// <exception cref = "ArgumentNullException">When both <paramref name = "executeMethod" /> and <paramref name = "canExecuteMethod" /> ar <see langword = "null" />.</exception>
|
||||||
|
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
|
||||||
|
: base((o) => executeMethod((T) o), (o) => canExecuteMethod((T) o))
|
||||||
|
{
|
||||||
|
if (executeMethod == null || canExecuteMethod == null)
|
||||||
|
throw new ArgumentNullException("executeMethod");
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Determines if the command can execute by invoked the <see cref = "Func{T,Bool}" /> provided during construction.
|
||||||
|
///</summary>
|
||||||
|
///<param name = "parameter">Data used by the command to determine if it can execute.</param>
|
||||||
|
///<returns>
|
||||||
|
/// <see langword = "true" /> if this command can be executed; otherwise, <see langword = "false" />.
|
||||||
|
///</returns>
|
||||||
|
public bool CanExecute(T parameter)
|
||||||
|
{
|
||||||
|
return base.CanExecute(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Executes the command and invokes the <see cref = "Action{T}" /> provided during construction.
|
||||||
|
///</summary>
|
||||||
|
///<param name = "parameter">Data used by the command.</param>
|
||||||
|
public void Execute(T parameter)
|
||||||
|
{
|
||||||
|
base.Execute(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref = "ICommand" /> whose delegates do not take any parameters for <see cref = "Execute" /> and <see cref = "CanExecute" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref = "DelegateCommandBase" />
|
||||||
|
/// <seealso cref = "DelegateCommand{T}" />
|
||||||
|
public class DelegateCommand : DelegateCommandBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref = "DelegateCommand" /> with the <see cref = "Action" /> to invoke on execution.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "executeMethod">The <see cref = "Action" /> to invoke when <see cref = "ICommand.Execute" /> is called.</param>
|
||||||
|
public DelegateCommand(Action executeMethod) : this(executeMethod, () => true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref = "DelegateCommand" /> with the <see cref = "Action" /> to invoke on execution
|
||||||
|
/// and a <see langword = "Func" /> to query for determining if the command can execute.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "executeMethod">The <see cref = "Action" /> to invoke when <see cref = "ICommand.Execute" /> is called.</param>
|
||||||
|
/// <param name = "canExecuteMethod">The <see cref = "Func{TResult}" /> to invoke when <see cref = "ICommand.CanExecute" /> is called</param>
|
||||||
|
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
|
||||||
|
: base((o) => executeMethod(), (o) => canExecuteMethod())
|
||||||
|
{
|
||||||
|
if (executeMethod == null || canExecuteMethod == null)
|
||||||
|
throw new ArgumentNullException("executeMethod");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Executes the command.
|
||||||
|
///</summary>
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Execute(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the command can be executed.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns <see langword = "true" /> if the command can execute,otherwise returns <see langword = "false" />.</returns>
|
||||||
|
public bool CanExecute()
|
||||||
|
{
|
||||||
|
return CanExecute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
95
Command/DelegateCommandBase.cs
Normal file
95
Command/DelegateCommandBase.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// Developed by doiTTeam => devdoiTTeam@gmail.com
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace DraggAnimatedPanelExample
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref = "ICommand" /> whose delegates can be attached for <see cref = "Execute" /> and <see cref = "CanExecute" />.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DelegateCommandBase : ICommand
|
||||||
|
{
|
||||||
|
private readonly Func<object, bool> canExecuteMethod;
|
||||||
|
private readonly Action<object> executeMethod;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Createse a new instance of a <see cref = "DelegateCommandBase" />, specifying both the execute action and the can execute function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "executeMethod">The <see cref = "Action" /> to execute when <see cref = "ICommand.Execute" /> is invoked.</param>
|
||||||
|
/// <param name = "canExecuteMethod">The <see cref = "Func{Object,Bool}" /> to invoked when <see cref = "ICommand.CanExecute" /> is invoked.</param>
|
||||||
|
protected DelegateCommandBase(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
|
||||||
|
{
|
||||||
|
if (executeMethod == null || canExecuteMethod == null)
|
||||||
|
throw new ArgumentNullException("executeMethod");
|
||||||
|
|
||||||
|
this.executeMethod = executeMethod;
|
||||||
|
this.canExecuteMethod = canExecuteMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ICommand Members
|
||||||
|
|
||||||
|
void ICommand.Execute(object parameter)
|
||||||
|
{
|
||||||
|
Execute(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICommand.CanExecute(object parameter)
|
||||||
|
{
|
||||||
|
return CanExecute(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when changes occur that affect whether or not the command should execute.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler CanExecuteChanged;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises <see cref = "ICommand.CanExecuteChanged" /> on the UI thread so every
|
||||||
|
/// command invoker can requery <see cref = "ICommand.CanExecute" /> to check if the
|
||||||
|
/// <see cref = "CompositeCommand" /> can execute.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnCanExecuteChanged()
|
||||||
|
{
|
||||||
|
var handlers = CanExecuteChanged;
|
||||||
|
if (handlers != null)
|
||||||
|
{
|
||||||
|
handlers(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises <see cref = "DelegateCommandBase.CanExecuteChanged" /> on the UI thread so every command invoker
|
||||||
|
/// can requery to check if the command can execute.
|
||||||
|
/// <remarks>
|
||||||
|
/// Note that this will trigger the execution of <see cref = "DelegateCommandBase.CanExecute" /> once for each invoker.
|
||||||
|
/// </remarks>
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
|
||||||
|
public void RaiseCanExecuteChanged()
|
||||||
|
{
|
||||||
|
OnCanExecuteChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes the command with the provided parameter by invoking the <see cref = "Action{Object}" /> supplied during construction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "parameter"></param>
|
||||||
|
protected void Execute(object parameter)
|
||||||
|
{
|
||||||
|
executeMethod(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the command can execute with the provided parameter by invoing the <see cref = "Func{Object,Bool}" /> supplied during construction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "parameter">The parameter to use when determining if this command can execute.</param>
|
||||||
|
/// <returns>Returns <see langword = "true" /> if the command can execute. <see langword = "False" /> otherwise.</returns>
|
||||||
|
protected bool CanExecute(object parameter)
|
||||||
|
{
|
||||||
|
return canExecuteMethod == null || canExecuteMethod(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Constant/DefaultConstant.cs
Normal file
18
Constant/DefaultConstant.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认参数
|
||||||
|
/// </summary>
|
||||||
|
namespace GeekDesk.Constant
|
||||||
|
{
|
||||||
|
enum DefaultConstant
|
||||||
|
{
|
||||||
|
WINDOW_WIDTH = 650, //默认窗体宽度
|
||||||
|
WINDOW_HEIGHT = 700, //默认窗体高度
|
||||||
|
MENU_CARD_WIDHT = 150 //默认菜单栏宽度
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Constant/SortType.cs
Normal file
15
Constant/SortType.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GeekDesk.Constant
|
||||||
|
{
|
||||||
|
enum SortType
|
||||||
|
{
|
||||||
|
CUSTOM = 1, //自定义排序
|
||||||
|
NAME = 2, //按名称排序
|
||||||
|
COUNT = 3 //按使用次数排序
|
||||||
|
}
|
||||||
|
}
|
||||||
205
DraggAnimatedPanel/DraggAnimatedPanel.Drag.cs
Normal file
205
DraggAnimatedPanel/DraggAnimatedPanel.Drag.cs
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
/*Developed by (doiTTeam)=>doiTTeam.mail = devdoiTTeam@gmail.com*/
|
||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
|
||||||
|
namespace DraggAnimatedPanel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of SafariPanel_Drag.
|
||||||
|
/// </summary>
|
||||||
|
public partial class DraggAnimatedPanel
|
||||||
|
{
|
||||||
|
#region const drag
|
||||||
|
const double mouseDif = 2d;
|
||||||
|
const int mouseTimeDif = 25;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region private
|
||||||
|
UIElement __draggedElement;
|
||||||
|
|
||||||
|
public UIElement _draggedElement {
|
||||||
|
get { return __draggedElement; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
__draggedElement = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int _draggedIndex;
|
||||||
|
|
||||||
|
bool _firstScrollRequest = true;
|
||||||
|
ScrollViewer _scrollContainer;
|
||||||
|
ScrollViewer scrollViewer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_firstScrollRequest && _scrollContainer == null)
|
||||||
|
{
|
||||||
|
_firstScrollRequest = false;
|
||||||
|
_scrollContainer = (ScrollViewer)GetParent(this as DependencyObject, (ve)=>ve is ScrollViewer);
|
||||||
|
}
|
||||||
|
return _scrollContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region private drag
|
||||||
|
double _lastMousePosX;
|
||||||
|
double _lastMousePosY;
|
||||||
|
int _lastMouseMoveTime;
|
||||||
|
double _x;
|
||||||
|
double _y;
|
||||||
|
Rect _rectOnDrag;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
void OnMouseMove(object sender,MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.LeftButton == MouseButtonState.Pressed && _draggedElement == null && !this.IsMouseCaptured)
|
||||||
|
StartDrag(e);
|
||||||
|
else if (_draggedElement != null)
|
||||||
|
OnDragOver(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDragOver(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
Point mousePos = Mouse.GetPosition(this);
|
||||||
|
double difX = mousePos.X - _lastMousePosX;
|
||||||
|
double difY = mousePos.Y - _lastMousePosY;
|
||||||
|
|
||||||
|
int timeDif = e.Timestamp - _lastMouseMoveTime;
|
||||||
|
if ((Math.Abs(difX) > mouseDif || Math.Abs(difY) > mouseDif) && timeDif > mouseTimeDif)
|
||||||
|
{
|
||||||
|
//this lines is for keepn draged item inside control bounds
|
||||||
|
DoScroll();
|
||||||
|
|
||||||
|
if (_x + difX < _rectOnDrag.Location.X)
|
||||||
|
_x = 0;
|
||||||
|
else if (ItemsWidth + _x + difX > _rectOnDrag.Location.X + _rectOnDrag.Width)
|
||||||
|
_x = _rectOnDrag.Location.X + _rectOnDrag.Width - ItemsWidth;
|
||||||
|
else if (mousePos.X > _rectOnDrag.Location.X && mousePos.X < _rectOnDrag.Location.X + _rectOnDrag.Width)
|
||||||
|
_x += difX;
|
||||||
|
if (_y + difY < _rectOnDrag.Location.Y)
|
||||||
|
_y = 0;
|
||||||
|
else if (ItemsHeight + _y + difY > _rectOnDrag.Location.Y + _rectOnDrag.Height)
|
||||||
|
_y = _rectOnDrag.Location.Y + _rectOnDrag.Height - ItemsHeight;
|
||||||
|
else if (mousePos.Y > _rectOnDrag.Location.Y && mousePos.Y < _rectOnDrag.Location.Y + _rectOnDrag.Height)
|
||||||
|
_y += difY;
|
||||||
|
//lines ends
|
||||||
|
|
||||||
|
AnimateTo(_draggedElement,_x,_y, 0);
|
||||||
|
_lastMousePosX = mousePos.X;
|
||||||
|
_lastMousePosY = mousePos.Y;
|
||||||
|
_lastMouseMoveTime = e.Timestamp;
|
||||||
|
SwapElement(_x + ItemsWidth/2 , _y + ItemsHeight/2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartDrag(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
Point mousePos = Mouse.GetPosition(this);
|
||||||
|
_draggedElement = GetChildThatHasMouseOver();
|
||||||
|
if (_draggedElement == null)
|
||||||
|
return;
|
||||||
|
_draggedIndex = Children.IndexOf(_draggedElement);
|
||||||
|
_rectOnDrag = VisualTreeHelper.GetDescendantBounds(this);
|
||||||
|
Point p = GetItemVisualPoint(_draggedElement);
|
||||||
|
_x = p.X;
|
||||||
|
_y = p.Y;
|
||||||
|
SetZIndex(_draggedElement,1000);
|
||||||
|
_lastMousePosX = mousePos.X;
|
||||||
|
_lastMousePosY = mousePos.Y;
|
||||||
|
_lastMouseMoveTime = e.Timestamp;
|
||||||
|
this.InvalidateArrange();
|
||||||
|
e.Handled = true;
|
||||||
|
this.CaptureMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMouseUp(object sender,MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.IsMouseCaptured)
|
||||||
|
ReleaseMouseCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapElement(double x, double y)
|
||||||
|
{
|
||||||
|
int index = GetIndexFromPoint(x,y);
|
||||||
|
if (index == _draggedIndex || index < 0)
|
||||||
|
return;
|
||||||
|
if (index >= Children.Count)
|
||||||
|
index = Children.Count - 1;
|
||||||
|
|
||||||
|
int[] parameter = new int[]{_draggedIndex, index};
|
||||||
|
if (SwapCommand != null && SwapCommand.CanExecute(parameter))
|
||||||
|
{
|
||||||
|
SwapCommand.Execute(parameter);
|
||||||
|
_draggedElement = Children[index]; //this is bcause after changing the collection the element is other
|
||||||
|
FillNewDraggedChild(_draggedElement);
|
||||||
|
_draggedIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.InvalidateArrange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillNewDraggedChild(UIElement child)
|
||||||
|
{
|
||||||
|
if (child.RenderTransform as TransformGroup == null)
|
||||||
|
{
|
||||||
|
child.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||||
|
TransformGroup group = new TransformGroup();
|
||||||
|
child.RenderTransform = group;
|
||||||
|
group.Children.Add(new TranslateTransform());
|
||||||
|
}
|
||||||
|
SetZIndex(child,1000);
|
||||||
|
AnimateTo(child,_x,_y, 0); //need relocate the element
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLostMouseCapture(object sender,MouseEventArgs e)
|
||||||
|
{
|
||||||
|
FinishDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FinishDrag()
|
||||||
|
{
|
||||||
|
if (_draggedElement != null)
|
||||||
|
{
|
||||||
|
SetZIndex(_draggedElement,0);
|
||||||
|
_draggedElement = null;
|
||||||
|
this.InvalidateArrange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoScroll()
|
||||||
|
{
|
||||||
|
if (scrollViewer != null)
|
||||||
|
{
|
||||||
|
Point position = Mouse.GetPosition(scrollViewer);
|
||||||
|
double scrollMargin = Math.Min(scrollViewer.FontSize * 2, scrollViewer.ActualHeight / 2);
|
||||||
|
|
||||||
|
if (position.X >= scrollViewer.ActualWidth - scrollMargin &&
|
||||||
|
scrollViewer.HorizontalOffset < scrollViewer.ExtentWidth - scrollViewer.ViewportWidth)
|
||||||
|
{
|
||||||
|
scrollViewer.LineRight();
|
||||||
|
}
|
||||||
|
else if (position.X < scrollMargin && scrollViewer.HorizontalOffset > 0)
|
||||||
|
{
|
||||||
|
scrollViewer.LineLeft();
|
||||||
|
}
|
||||||
|
else if (position.Y >= scrollViewer.ActualHeight - scrollMargin &&
|
||||||
|
scrollViewer.VerticalOffset < scrollViewer.ExtentHeight - scrollViewer.ViewportHeight)
|
||||||
|
{
|
||||||
|
scrollViewer.LineDown();
|
||||||
|
}
|
||||||
|
else if (position.Y < scrollMargin && scrollViewer.VerticalOffset > 0)
|
||||||
|
{
|
||||||
|
scrollViewer.LineUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
237
DraggAnimatedPanel/DraggAnimatedPanel.cs
Normal file
237
DraggAnimatedPanel/DraggAnimatedPanel.cs
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/*Developed by (doiTTeam)=>doiTTeam.mail = devdoiTTeam@gmail.com*/
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
|
||||||
|
namespace DraggAnimatedPanel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of DraggAnimatedPanel.
|
||||||
|
/// </summary>
|
||||||
|
public partial class DraggAnimatedPanel : WrapPanel
|
||||||
|
{
|
||||||
|
#region private vars
|
||||||
|
Size _calculatedSize;
|
||||||
|
bool _isNotFirstArrange = false;
|
||||||
|
int columns, rows;
|
||||||
|
#endregion
|
||||||
|
static DraggAnimatedPanel()
|
||||||
|
{
|
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(DraggAnimatedPanel), new FrameworkPropertyMetadata(typeof(DraggAnimatedPanel)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DraggAnimatedPanel() : base()
|
||||||
|
{
|
||||||
|
this.AddHandler(Mouse.MouseMoveEvent, new MouseEventHandler(OnMouseMove), false);
|
||||||
|
this.MouseLeftButtonUp += OnMouseUp;
|
||||||
|
this.LostMouseCapture += OnLostMouseCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIElement GetChildThatHasMouseOver()
|
||||||
|
{
|
||||||
|
return GetParent(Mouse.DirectlyOver as DependencyObject, (ve) => Children.Contains(ve as UIElement)) as UIElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point GetItemVisualPoint(UIElement element)
|
||||||
|
{
|
||||||
|
TransformGroup group = (TransformGroup)element.RenderTransform;
|
||||||
|
TranslateTransform trans = (TranslateTransform)group.Children[0];
|
||||||
|
|
||||||
|
return new Point(trans.X, trans.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetIndexFromPoint(double x, double y)
|
||||||
|
{
|
||||||
|
int columnIndex = (int)Math.Truncate(x / itemContainterWidth);
|
||||||
|
int rowIndex = (int)Math.Truncate(y / itemContainterHeight);
|
||||||
|
return columns * rowIndex + columnIndex;
|
||||||
|
}
|
||||||
|
int GetIndexFromPoint(Point p)
|
||||||
|
{
|
||||||
|
return GetIndexFromPoint(p.X, p.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region dependency properties
|
||||||
|
public static readonly DependencyProperty ItemsWidthProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"ItemsWidth",
|
||||||
|
typeof(double),
|
||||||
|
typeof(DraggAnimatedPanel),
|
||||||
|
new FrameworkPropertyMetadata(150d));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ItemsHeightProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"ItemsHeight",
|
||||||
|
typeof(double),
|
||||||
|
typeof(DraggAnimatedPanel),
|
||||||
|
new FrameworkPropertyMetadata(60d));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ItemSeparationProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"ItemSeparation",
|
||||||
|
typeof(Thickness),
|
||||||
|
typeof(DraggAnimatedPanel),
|
||||||
|
new FrameworkPropertyMetadata());
|
||||||
|
|
||||||
|
// Using a DependencyProperty as the backing store for AnimationMilliseconds. This enables animation, styling, binding, etc...
|
||||||
|
public static readonly DependencyProperty AnimationMillisecondsProperty =
|
||||||
|
DependencyProperty.Register("AnimationMilliseconds", typeof(int), typeof(DraggAnimatedPanel), new FrameworkPropertyMetadata(200));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty SwapCommandProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"SwapCommand",
|
||||||
|
typeof(ICommand),
|
||||||
|
typeof(DraggAnimatedPanel),
|
||||||
|
new FrameworkPropertyMetadata(null));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region properties
|
||||||
|
public double ItemsWidth
|
||||||
|
{
|
||||||
|
get { return (double)GetValue(ItemsWidthProperty); }
|
||||||
|
set { SetValue(ItemsWidthProperty, value); }
|
||||||
|
}
|
||||||
|
public double ItemsHeight
|
||||||
|
{
|
||||||
|
get { return (double)GetValue(ItemsHeightProperty); }
|
||||||
|
set { SetValue(ItemsHeightProperty, value); }
|
||||||
|
}
|
||||||
|
public Thickness ItemSeparation
|
||||||
|
{
|
||||||
|
get { return (Thickness)this.GetValue(ItemSeparationProperty); }
|
||||||
|
set { this.SetValue(ItemSeparationProperty, value); }
|
||||||
|
}
|
||||||
|
public int AnimationMilliseconds
|
||||||
|
{
|
||||||
|
get { return (int)GetValue(AnimationMillisecondsProperty); }
|
||||||
|
set { SetValue(AnimationMillisecondsProperty, value); }
|
||||||
|
}
|
||||||
|
private double itemContainterHeight
|
||||||
|
{
|
||||||
|
get { return ItemSeparation.Top + ItemsHeight + ItemSeparation.Bottom; }
|
||||||
|
}
|
||||||
|
private double itemContainterWidth
|
||||||
|
{
|
||||||
|
get { return ItemSeparation.Left + ItemsWidth + ItemSeparation.Right; }
|
||||||
|
}
|
||||||
|
public ICommand SwapCommand
|
||||||
|
{
|
||||||
|
get { return (ICommand)GetValue(SwapCommandProperty); }
|
||||||
|
set { SetValue(SwapCommandProperty, value); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region transformation things
|
||||||
|
private void AnimateAll()
|
||||||
|
{
|
||||||
|
//Apply exactly the same algorithm, but instide of Arrange a call AnimateTo method
|
||||||
|
double colPosition = 0;
|
||||||
|
double rowPosition = 0;
|
||||||
|
foreach (UIElement child in Children)
|
||||||
|
{
|
||||||
|
if (child != _draggedElement)
|
||||||
|
AnimateTo(child, colPosition + ItemSeparation.Left, rowPosition + ItemSeparation.Top, _isNotFirstArrange ? AnimationMilliseconds : 0);
|
||||||
|
//drag will locate dragged element
|
||||||
|
colPosition += itemContainterWidth;
|
||||||
|
if (colPosition + 1 > _calculatedSize.Width)
|
||||||
|
{
|
||||||
|
colPosition = 0;
|
||||||
|
rowPosition += itemContainterHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AnimateTo(UIElement child, double x, double y, int duration)
|
||||||
|
{
|
||||||
|
TransformGroup group = (TransformGroup)child.RenderTransform;
|
||||||
|
TranslateTransform trans = (TranslateTransform)group.Children.First((groupElement) => groupElement is TranslateTransform);
|
||||||
|
|
||||||
|
trans.BeginAnimation(TranslateTransform.XProperty, MakeAnimation(x, duration));
|
||||||
|
trans.BeginAnimation(TranslateTransform.YProperty, MakeAnimation(y, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DoubleAnimation MakeAnimation(double to, int duration)
|
||||||
|
{
|
||||||
|
DoubleAnimation anim = new DoubleAnimation(to, TimeSpan.FromMilliseconds(duration));
|
||||||
|
anim.AccelerationRatio = 0.2;
|
||||||
|
anim.DecelerationRatio = 0.7;
|
||||||
|
return anim;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region measure
|
||||||
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
|
{
|
||||||
|
Size itemContainerSize = new Size(itemContainterWidth, itemContainterHeight);
|
||||||
|
int count = 0; //for not call it again
|
||||||
|
foreach (UIElement child in Children)
|
||||||
|
{
|
||||||
|
child.Measure(itemContainerSize);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (availableSize.Width < itemContainterWidth)
|
||||||
|
_calculatedSize = new Size(itemContainterWidth, count * itemContainterHeight); //the size of nX1
|
||||||
|
else
|
||||||
|
{
|
||||||
|
columns = (int)Math.Truncate(availableSize.Width / itemContainterWidth);
|
||||||
|
rows = count / columns;
|
||||||
|
if (count % columns != 0)
|
||||||
|
rows++;
|
||||||
|
_calculatedSize = new Size(columns * itemContainterWidth, rows * itemContainterHeight);
|
||||||
|
}
|
||||||
|
return _calculatedSize;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region arrange
|
||||||
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
|
{
|
||||||
|
Size _finalItemSize = new Size(ItemsWidth, ItemsHeight);
|
||||||
|
//if is animated then arrange elements to 0,0, and then put them on its location using the transform
|
||||||
|
foreach (UIElement child in InternalChildren)
|
||||||
|
{
|
||||||
|
// If this is the first time we've seen this child, add our transforms
|
||||||
|
if (child.RenderTransform as TransformGroup == null)
|
||||||
|
{
|
||||||
|
child.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||||
|
TransformGroup group = new TransformGroup();
|
||||||
|
child.RenderTransform = group;
|
||||||
|
group.Children.Add(new TranslateTransform());
|
||||||
|
}
|
||||||
|
//locate all children in 0,0 point//TODO: use infinity and then scale each element to items size
|
||||||
|
child.Arrange(new Rect(new Point(0, 0), _finalItemSize)); //when use transformations change to childs.DesireSize
|
||||||
|
}
|
||||||
|
AnimateAll();
|
||||||
|
|
||||||
|
if (!_isNotFirstArrange)
|
||||||
|
_isNotFirstArrange = true;
|
||||||
|
|
||||||
|
return _calculatedSize;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Static
|
||||||
|
//this can be an extension method
|
||||||
|
public static DependencyObject GetParent(DependencyObject o, Func<DependencyObject, bool> matchFunction)
|
||||||
|
{
|
||||||
|
DependencyObject t = o;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
t = VisualTreeHelper.GetParent(t);
|
||||||
|
} while (t != null && !matchFunction.Invoke(t));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//TODO: Add IsEditing property
|
||||||
|
//TODO: Add Scale transform to items for fill items area
|
||||||
|
}
|
||||||
|
}
|
||||||
146
GeekDesk.csproj
Normal file
146
GeekDesk.csproj
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{B4983CEC-2281-413C-8ECF-92EE0E40A713}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>GeekDesk</RootNamespace>
|
||||||
|
<AssemblyName>GeekDesk</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="CommonServiceLocator, Version=2.0.6.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\CommonServiceLocator.2.0.6\lib\net45\CommonServiceLocator.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="GalaSoft.MvvmLight, Version=5.4.1.0, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="GalaSoft.MvvmLight.Extras, Version=5.4.1.0, Culture=neutral, PublicKeyToken=669f0b5e8f868abf, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="GalaSoft.MvvmLight.Platform, Version=5.4.1.0, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="HandyControl, Version=3.1.0.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\HandyControl.3.1.0\lib\net452\HandyControl.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Drawing.Common, Version=4.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\System.Drawing.Common.5.0.2\lib\net461\System.Drawing.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\MvvmLightLibs.5.4.1.1\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xaml">
|
||||||
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="Command\DelegateCommand.cs" />
|
||||||
|
<Compile Include="Command\DelegateCommandBase.cs" />
|
||||||
|
<Compile Include="Constant\DefaultConstant.cs" />
|
||||||
|
<Compile Include="Constant\SortType.cs" />
|
||||||
|
<Compile Include="DraggAnimatedPanel\DraggAnimatedPanel.cs" />
|
||||||
|
<Compile Include="DraggAnimatedPanel\DraggAnimatedPanel.Drag.cs" />
|
||||||
|
<Compile Include="Util\CommonCode.cs" />
|
||||||
|
<Compile Include="Util\ConsoleManager.cs" />
|
||||||
|
<Compile Include="Util\DragAdorner.cs" />
|
||||||
|
<Compile Include="Util\FileIcon.cs" />
|
||||||
|
<Compile Include="Util\ListViewDragDropManager.cs" />
|
||||||
|
<Compile Include="Util\MenuWidthConvert.cs" />
|
||||||
|
<Compile Include="Util\MouseUtilities.cs" />
|
||||||
|
<Compile Include="Util\SystemIcon.cs" />
|
||||||
|
<Compile Include="ViewModel\AppConfig.cs" />
|
||||||
|
<Compile Include="ViewModel\DataInfos.cs" />
|
||||||
|
<Compile Include="ViewModel\MainModel.cs" />
|
||||||
|
<Compile Include="ViewModel\MainViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\MenuViewModel.cs" />
|
||||||
|
<Page Include="MainWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Compile Include="App.xaml.cs">
|
||||||
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="MainWindow.xaml.cs">
|
||||||
|
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
25
GeekDesk.sln
Normal file
25
GeekDesk.sln
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Blend for Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30907.101
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeekDesk", "GeekDesk.csproj", "{B4983CEC-2281-413C-8ECF-92EE0E40A713}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B4983CEC-2281-413C-8ECF-92EE0E40A713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B4983CEC-2281-413C-8ECF-92EE0E40A713}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B4983CEC-2281-413C-8ECF-92EE0E40A713}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B4983CEC-2281-413C-8ECF-92EE0E40A713}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {7D844F27-975B-4CFF-A373-E665FB8866DE}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
219
MainWindow.xaml
Normal file
219
MainWindow.xaml
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
<Window x:Class="GeekDesk.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:GeekDesk"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
xmlns:util="clr-namespace:GeekDesk.Util"
|
||||||
|
xmlns:DraggAnimatedPanel="clr-namespace:DraggAnimatedPanel" x:Name="window"
|
||||||
|
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||||
|
Title="MainWindow" Height="450" Width="800">
|
||||||
|
<Window.Resources>
|
||||||
|
|
||||||
|
<Style x:Key="ListBoxStyle" BasedOn="{StaticResource ListBoxBaseStyle}" TargetType="ListBox"/>
|
||||||
|
<Style TargetType="{x:Type ListBoxItem}" x:Key="memuStory" BasedOn="{StaticResource ListBoxStyle}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<!--鼠标移入-->
|
||||||
|
<EventTrigger RoutedEvent="MouseMove">
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<!--鼠标移入放大-->
|
||||||
|
<DoubleAnimation To="20" Duration="0:0:0.001" Storyboard.TargetProperty="FontSize"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</EventTrigger>
|
||||||
|
<!--鼠标移出-->
|
||||||
|
<EventTrigger RoutedEvent="MouseLeave">
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<!--鼠标移出恢复正常大小-->
|
||||||
|
<DoubleAnimation To="15" Duration="0:0:0.001" Storyboard.TargetProperty="FontSize"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</EventTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
<!--左侧栏样式动画-->
|
||||||
|
<Style x:Key="menuStyle" TargetType="ListBoxItem" BasedOn="{StaticResource ListBoxItemBaseStyle}">
|
||||||
|
<Setter Property="FontSize" Value="15"/>
|
||||||
|
<Setter Property="RenderTransform">
|
||||||
|
<Setter.Value>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style.Triggers>
|
||||||
|
<MultiTrigger>
|
||||||
|
<MultiTrigger.Conditions>
|
||||||
|
<Condition Property="IsMouseOver" Value="True"/>
|
||||||
|
</MultiTrigger.Conditions>
|
||||||
|
<MultiTrigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation To="20" Duration="0:0:0.001" Storyboard.TargetProperty="FontSize"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</MultiTrigger.EnterActions>
|
||||||
|
<MultiTrigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation To="15" Duration="0:0:0.5" Storyboard.TargetProperty="FontSize"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</MultiTrigger.ExitActions>
|
||||||
|
</MultiTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!--右侧栏样式动画-->
|
||||||
|
<Style x:Key="imageStyle" TargetType="Image">
|
||||||
|
<Setter Property="Width" Value="60"/>
|
||||||
|
<Setter Property="Height" Value="60"/>
|
||||||
|
<Setter Property="Source" Value="{Binding BitmapImage}"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<MultiTrigger>
|
||||||
|
<MultiTrigger.Conditions>
|
||||||
|
<Condition Property="IsMouseOver" Value="True"/>
|
||||||
|
</MultiTrigger.Conditions>
|
||||||
|
<MultiTrigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation To="80" Duration="0:0:0.1" Storyboard.TargetProperty="Width"/>
|
||||||
|
<DoubleAnimation To="80" Duration="0:0:0.1" Storyboard.TargetProperty="Height"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</MultiTrigger.EnterActions>
|
||||||
|
<MultiTrigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation To="60" Duration="0:0:0.5" Storyboard.TargetProperty="Width"/>
|
||||||
|
<DoubleAnimation To="60" Duration="0:0:0.5" Storyboard.TargetProperty="Height"/>
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</MultiTrigger.ExitActions>
|
||||||
|
</MultiTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<util:MenuWidthConvert x:Key="MenuWidthConvert"/>
|
||||||
|
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<!--背景图片-->
|
||||||
|
<Grid.Background>
|
||||||
|
<ImageBrush ImageSource="D:\壁纸\18078.jpg"></ImageBrush>
|
||||||
|
</Grid.Background>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="40"></RowDefinition>
|
||||||
|
<RowDefinition Height="*"></RowDefinition>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="leftColumn" MinWidth="80" Width="150" MaxWidth="200"></ColumnDefinition>
|
||||||
|
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<DockPanel Grid.Row="0" Grid.Column="0">
|
||||||
|
<Label>Text</Label>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<!--左侧栏-->
|
||||||
|
<hc:Card Opacity="1" x:Name="leftCard" Grid.Row="1" Grid.Column="0"
|
||||||
|
BorderThickness="1"
|
||||||
|
Effect="{DynamicResource EffectShadow2}"
|
||||||
|
Margin="5,5,0,5"
|
||||||
|
>
|
||||||
|
<!--<hc:Card.ContextMenu>
|
||||||
|
<ContextMenu Width="200">
|
||||||
|
<TextBlock Text="新建菜单"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</hc:Card.ContextMenu>-->
|
||||||
|
<!--<ListBox x:Name="menu" BorderThickness="0" ItemsSource="{Binding}" Margin="10,8,10,8"
|
||||||
|
>
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding menu}" FontSize="15" Style="{StaticResource memuStory}" PreviewMouseLeftButtonDown="menuClick" RenderTransformOrigin="0.5,0.5">
|
||||||
|
|
||||||
|
</TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>-->
|
||||||
|
|
||||||
|
<ListBox x:Name="menu" ItemsSource="{Binding}">
|
||||||
|
<ListBox.Resources>
|
||||||
|
<ContextMenu x:Key="menuDialog" Width="200">
|
||||||
|
<MenuItem Header="新建菜单"/>
|
||||||
|
<MenuItem Header="重命名"/>
|
||||||
|
<MenuItem Header="删除" Click="deleteMenu"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</ListBox.Resources>
|
||||||
|
|
||||||
|
<ListBox.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListBoxItem" BasedOn="{StaticResource menuStyle}">
|
||||||
|
<Setter Property="ContextMenu" Value="{StaticResource menuDialog}"/>
|
||||||
|
</Style>
|
||||||
|
</ListBox.ItemContainerStyle>
|
||||||
|
<ListBox.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<DraggAnimatedPanel:DraggAnimatedPanel ItemsHeight="30" ItemsWidth="{Binding ElementName=leftColumn, Path=Width, Converter={StaticResource MenuWidthConvert}}" HorizontalAlignment="Center" VerticalAlignment="Top" SwapCommand="{Binding SwapCommand2, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListBox.ItemsPanel>
|
||||||
|
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding menu}" PreviewMouseLeftButtonDown="menuClick" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</hc:Card>
|
||||||
|
<!--分割线-->
|
||||||
|
<GridSplitter Opacity="0" Grid.Row="1" Grid.Column="0" Width="1" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
|
||||||
|
|
||||||
|
<!--右侧栏-->
|
||||||
|
<hc:Card AllowDrop="True" Drop="Wrap_Drop" Opacity="1" x:Name="rightCard" Grid.Row="1" Grid.Column="1" BorderThickness="1" Effect="{DynamicResource EffectShadow2}" Margin="5,5,5,5">
|
||||||
|
<WrapPanel Orientation="Horizontal">
|
||||||
|
<ListBox x:Name="data" ItemsSource="{Binding}"
|
||||||
|
BorderThickness="0"
|
||||||
|
SelectionChanged="data_SelectionChanged"
|
||||||
|
>
|
||||||
|
<!--<ListBox.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource dataStyle}"/>
|
||||||
|
</ListBox.ItemContainerStyle>-->
|
||||||
|
<ListBox.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<DraggAnimatedPanel:DraggAnimatedPanel ItemsHeight="115" ItemsWidth="100" HorizontalAlignment="Center" SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListBox.ItemsPanel>
|
||||||
|
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Border Margin="5,5,5,5" CornerRadius="10">
|
||||||
|
<StackPanel Tag="{Binding Path}"
|
||||||
|
MouseLeftButtonDown="dataClick"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
hc:Poptip.HitMode="None"
|
||||||
|
hc:Poptip.IsOpen="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
|
||||||
|
hc:Poptip.Content="{Binding Path}"
|
||||||
|
hc:Poptip.Placement="BottomLeft"
|
||||||
|
Margin="5,5,5,5"
|
||||||
|
Height="115"
|
||||||
|
>
|
||||||
|
<Image Style="{StaticResource imageStyle}"></Image>
|
||||||
|
<TextBlock Width="80" TextWrapping="Wrap" TextAlignment="Center" Height="35" LineHeight="15" FontSize="12" Text="{Binding Name}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</WrapPanel>
|
||||||
|
|
||||||
|
</hc:Card>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
324
MainWindow.xaml.cs
Normal file
324
MainWindow.xaml.cs
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
using GeekDesk.ViewModel;
|
||||||
|
using System.IO;
|
||||||
|
using GeekDesk.Util;
|
||||||
|
using GalaSoft.MvvmLight;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using WPF.JoshSmith.ServiceProviders.UI;
|
||||||
|
using DraggAnimatedPanelExample;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace GeekDesk
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// MainWindow.xaml 的交互逻辑
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
private static MainModel mainModel;
|
||||||
|
|
||||||
|
ListViewDragDropManager<ViewModel.Menu> dragMgr;
|
||||||
|
ListViewDragDropManager<ViewModel.DataInfos> dragMgr2;
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
mainModel = new MainModel();
|
||||||
|
//this.DataContext = mainModel;
|
||||||
|
//menu.Items = mainModel;
|
||||||
|
//System.Diagnostics.Process.Start(@"D:\SoftWare\WeGame\wegame.exe");
|
||||||
|
this.Loaded += Window_Loaded;
|
||||||
|
this.SizeChanged += MainWindow_Resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateCommand<int[]> _swap;
|
||||||
|
public DelegateCommand<int[]> SwapCommand
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_swap == null)
|
||||||
|
_swap = new DelegateCommand<int[]>(
|
||||||
|
(indexes) =>
|
||||||
|
{
|
||||||
|
int fromS = indexes[0];
|
||||||
|
int to = indexes[1];
|
||||||
|
var elementSource = data.Items[to];
|
||||||
|
var dragged = data.Items[fromS];
|
||||||
|
if (fromS > to)
|
||||||
|
{
|
||||||
|
data.Items.Remove(dragged);
|
||||||
|
data.Items.Insert(to, dragged);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.Items.Remove(dragged);
|
||||||
|
data.Items.Insert(to, dragged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return _swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DelegateCommand<int[]> _swap2;
|
||||||
|
public DelegateCommand<int[]> SwapCommand2
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_swap2 == null)
|
||||||
|
_swap2 = new DelegateCommand<int[]>(
|
||||||
|
(indexes) =>
|
||||||
|
{
|
||||||
|
int fromS = indexes[0];
|
||||||
|
int to = indexes[1];
|
||||||
|
var elementSource = menu.Items[to];
|
||||||
|
var dragged = menu.Items[fromS];
|
||||||
|
if (fromS > to)
|
||||||
|
{
|
||||||
|
menu.Items.Remove(dragged);
|
||||||
|
menu.Items.Insert(to, dragged);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu.Items.Remove(dragged);
|
||||||
|
menu.Items.Insert(to, dragged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return _swap2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void Wrap_Drop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
Array dropObject = (System.Array)e.Data.GetData(DataFormats.FileDrop);
|
||||||
|
if (dropObject == null) return;
|
||||||
|
string path = (string)dropObject.GetValue(0);
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
// 文件
|
||||||
|
BitmapImage bi = FileIcon.GetBitmapImage(path);
|
||||||
|
DataInfos infos = new DataInfos();
|
||||||
|
infos.Path = path;
|
||||||
|
infos.BitmapImage = bi;
|
||||||
|
infos.Name = Path.GetFileNameWithoutExtension(path);
|
||||||
|
data.Items.Add(infos);
|
||||||
|
data.Items.Refresh();
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
//文件夹
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//菜单点击事件
|
||||||
|
private void menuClick(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图标点击事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void dataClick(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
//string path = ((StackPanel)sender).Tag.ToString();
|
||||||
|
//System.Diagnostics.Process.Start(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// data选中事件 设置不可选中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void data_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (data.SelectedIndex != -1) data.SelectedIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Window_Loaded
|
||||||
|
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
AppConfig config = CommonCode.GetAppConfig();
|
||||||
|
this.Width = config.WindowWidth;
|
||||||
|
this.Height = config.WindowHeight;
|
||||||
|
this.DataContext = config;
|
||||||
|
|
||||||
|
this.menu.Items.Add(new ViewModel.Menu() { menu = "test1" });
|
||||||
|
this.menu.Items.Add(new ViewModel.Menu() { menu = "test2" });
|
||||||
|
this.menu.Items.Add(new ViewModel.Menu() { menu = "test3" });
|
||||||
|
}
|
||||||
|
#endregion // Window_Loaded
|
||||||
|
|
||||||
|
#region Window_Closing
|
||||||
|
void Window_Closing(object sender, CancelEventArgs e)
|
||||||
|
{
|
||||||
|
Rect rect = this.RestoreBounds;
|
||||||
|
AppConfig config = this.DataContext as AppConfig;
|
||||||
|
config.WindowWidth = rect.Width;
|
||||||
|
config.WindowHeight = rect.Height;
|
||||||
|
CommonCode.SaveAppConfig(config);
|
||||||
|
}
|
||||||
|
#endregion // Window_Closing
|
||||||
|
|
||||||
|
void MainWindow_Resize(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.DataContext != null)
|
||||||
|
{
|
||||||
|
AppConfig config = this.DataContext as AppConfig;
|
||||||
|
config.WindowWidth = this.Width;
|
||||||
|
config.WindowHeight = this.Height;
|
||||||
|
CommonCode.SaveAppConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region dragMgr_ProcessDrop
|
||||||
|
|
||||||
|
// Performs custom drop logic for the top ListView.
|
||||||
|
void dragMgr_ProcessDrop(object sender, ProcessDropEventArgs<object> e)
|
||||||
|
{
|
||||||
|
// This shows how to customize the behavior of a drop.
|
||||||
|
// Here we perform a swap, instead of just moving the dropped item.
|
||||||
|
|
||||||
|
int higherIdx = Math.Max(e.OldIndex, e.NewIndex);
|
||||||
|
int lowerIdx = Math.Min(e.OldIndex, e.NewIndex);
|
||||||
|
|
||||||
|
if (lowerIdx < 0)
|
||||||
|
{
|
||||||
|
// The item came from the lower ListView
|
||||||
|
// so just insert it.
|
||||||
|
e.ItemsSource.Insert(higherIdx, e.DataItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// null values will cause an error when calling Move.
|
||||||
|
// It looks like a bug in ObservableCollection to me.
|
||||||
|
if (e.ItemsSource[lowerIdx] == null ||
|
||||||
|
e.ItemsSource[higherIdx] == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The item came from the ListView into which
|
||||||
|
// it was dropped, so swap it with the item
|
||||||
|
// at the target index.
|
||||||
|
e.ItemsSource.Move(lowerIdx, higherIdx);
|
||||||
|
e.ItemsSource.Move(higherIdx - 1, lowerIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this to 'Move' so that the OnListViewDrop knows to
|
||||||
|
// remove the item from the other ListView.
|
||||||
|
e.Effects = DragDropEffects.Move;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // dragMgr_ProcessDrop
|
||||||
|
|
||||||
|
#region OnListViewDragEnter
|
||||||
|
|
||||||
|
// Handles the DragEnter event for both ListViews.
|
||||||
|
void OnListViewDragEnter(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
e.Effects = DragDropEffects.Move;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // OnListViewDragEnter
|
||||||
|
|
||||||
|
#region OnListViewDrop
|
||||||
|
|
||||||
|
// Handles the Drop event for both ListViews.
|
||||||
|
void OnListViewDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Effects == DragDropEffects.None)
|
||||||
|
return;
|
||||||
|
ViewModel.Menu menuV = e.Data.GetData(typeof(ViewModel.Menu)) as ViewModel.Menu;
|
||||||
|
DataInfos data = e.Data.GetData(typeof(DataInfos)) as DataInfos;
|
||||||
|
|
||||||
|
if (sender == this.menu)
|
||||||
|
{
|
||||||
|
if (this.dragMgr.IsDragInProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// An item was dragged from the bottom ListView into the top ListView
|
||||||
|
// so remove that item from the bottom ListView.
|
||||||
|
(this.data.ItemsSource as ObservableCollection<DataInfos>).Remove(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this.dragMgr2.IsDragInProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// An item was dragged from the top ListView into the bottom ListView
|
||||||
|
// so remove that item from the top ListView.
|
||||||
|
(this.menu.ItemsSource as ObservableCollection<ViewModel.Menu>).Remove(menuV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // OnListViewDrop
|
||||||
|
|
||||||
|
private void leftCard_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteMenu(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
//if (data.SelectedIndex == -1)
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
ViewModel.Menu pojo = (ViewModel.Menu)((ContextMenu)((MenuItem)sender).Parent).DataContext;
|
||||||
|
string menuTitle = pojo.menu;
|
||||||
|
int index = 0;
|
||||||
|
foreach (object obj in menu.Items)
|
||||||
|
{
|
||||||
|
string test = ((ViewModel.Menu)obj).menu;
|
||||||
|
if (test == menuTitle)
|
||||||
|
{
|
||||||
|
menu.Items.RemoveAt(index);
|
||||||
|
menu.Items.Refresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double ConvertString(string val)
|
||||||
|
{
|
||||||
|
return Convert.ToDouble(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class MainModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public List<ViewModel.Menu> MenuList { get; set; }
|
||||||
|
|
||||||
|
public List<ViewModel.DataInfos> DataList { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
55
Properties/AssemblyInfo.cs
Normal file
55
Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
// 有关程序集的一般信息由以下
|
||||||
|
// 控制。更改这些特性值可修改
|
||||||
|
// 与程序集关联的信息。
|
||||||
|
[assembly: AssemblyTitle("GeekDesk")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("GeekDesk")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||||
|
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||||
|
//请将此类型的 ComVisible 特性设置为 true。
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
//若要开始生成可本地化的应用程序,请设置
|
||||||
|
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||||
|
//例如,如果您在源文件中使用的是美国英语,
|
||||||
|
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||||
|
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||||
|
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||||
|
//(未在页面中找到资源时使用,
|
||||||
|
//或应用程序资源字典中找到时使用)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||||
|
//(未在页面中找到资源时使用,
|
||||||
|
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||||
|
)]
|
||||||
|
|
||||||
|
|
||||||
|
// 程序集的版本信息由下列四个值组成:
|
||||||
|
//
|
||||||
|
// 主版本
|
||||||
|
// 次版本
|
||||||
|
// 生成号
|
||||||
|
// 修订号
|
||||||
|
//
|
||||||
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
|
//通过使用 "*",如下所示:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
63
Properties/Resources.Designer.cs
generated
Normal file
63
Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 此代码由工具生成。
|
||||||
|
// 运行时版本:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||||
|
// 重新生成代码,这些更改将会丢失。
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace GeekDesk.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||||
|
/// </summary>
|
||||||
|
// 此类是由 StronglyTypedResourceBuilder
|
||||||
|
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||||
|
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||||
|
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GeekDesk.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||||
|
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
117
Properties/Resources.resx
Normal file
117
Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
26
Properties/Settings.Designer.cs
generated
Normal file
26
Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 此代码由工具生成。
|
||||||
|
// 运行时版本:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||||
|
// 重新生成代码,这些更改将会丢失。
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace GeekDesk.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default {
|
||||||
|
get {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Properties/Settings.settings
Normal file
7
Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
||||||
59
Util/CommonCode.cs
Normal file
59
Util/CommonCode.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GeekDesk.ViewModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提取一些代码
|
||||||
|
/// </summary>
|
||||||
|
namespace GeekDesk.Util
|
||||||
|
{
|
||||||
|
class CommonCode
|
||||||
|
{
|
||||||
|
private static string appConfigFilePath = AppDomain.CurrentDomain.BaseDirectory.Trim() + "\\config";
|
||||||
|
/// <summary>
|
||||||
|
/// 获取app配置
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static AppConfig GetAppConfig()
|
||||||
|
{
|
||||||
|
AppConfig config;
|
||||||
|
if (!File.Exists(appConfigFilePath))
|
||||||
|
{
|
||||||
|
using (FileStream fs = File.Create(appConfigFilePath)) { }
|
||||||
|
config = new AppConfig();
|
||||||
|
SaveAppConfig(config);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(appConfigFilePath, FileMode.Open))
|
||||||
|
{
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
string json = bf.Deserialize(fs) as string;
|
||||||
|
config = JsonConvert.DeserializeObject<AppConfig>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存app配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
public static void SaveAppConfig(AppConfig config)
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(appConfigFilePath, FileMode.Create))
|
||||||
|
{
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
string json = JsonConvert.SerializeObject(config);
|
||||||
|
bf.Serialize(fs, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
Util/ConsoleManager.cs
Normal file
105
Util/ConsoleManager.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GeekDesk.Util
|
||||||
|
{
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
public static class ConsoleManager
|
||||||
|
{
|
||||||
|
private const string Kernel32_DllName = "kernel32.dll";
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool AllocConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool FreeConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern IntPtr GetConsoleWindow();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern int GetConsoleOutputCP();
|
||||||
|
|
||||||
|
public static bool HasConsole
|
||||||
|
{
|
||||||
|
get { return GetConsoleWindow() != IntPtr.Zero; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new console instance if the process is not attached to a console already.
|
||||||
|
/// </summary>
|
||||||
|
public static void Show()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (!HasConsole)
|
||||||
|
{
|
||||||
|
AllocConsole();
|
||||||
|
InvalidateOutAndError();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
|
||||||
|
/// </summary>
|
||||||
|
public static void Hide()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
SetOutAndErrorNull();
|
||||||
|
FreeConsole();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Toggle()
|
||||||
|
{
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InvalidateOutAndError()
|
||||||
|
{
|
||||||
|
Type type = typeof(System.Console);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _out = type.GetField("_out",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _error = type.GetField("_error",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
Debug.Assert(_out != null);
|
||||||
|
Debug.Assert(_error != null);
|
||||||
|
|
||||||
|
Debug.Assert(_InitializeStdOutError != null);
|
||||||
|
|
||||||
|
_out.SetValue(null, null);
|
||||||
|
_error.SetValue(null, null);
|
||||||
|
|
||||||
|
_InitializeStdOutError.Invoke(null, new object[] { true });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetOutAndErrorNull()
|
||||||
|
{
|
||||||
|
Console.SetOut(TextWriter.Null);
|
||||||
|
Console.SetError(TextWriter.Null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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 WPF.JoshSmith.Adorners
|
||||||
|
{
|
||||||
|
/// <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
|
||||||
|
}
|
||||||
|
}
|
||||||
376
Util/FileIcon.cs
Normal file
376
Util/FileIcon.cs
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace GeekDesk.Util
|
||||||
|
{
|
||||||
|
class FileIcon
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public static Icon GetIcon(string filePath)
|
||||||
|
{
|
||||||
|
IntPtr hIcon = GetJumboIcon(GetIconIndex(filePath));
|
||||||
|
Icon ico = Icon.FromHandle(hIcon);
|
||||||
|
return ico;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitmapImage GetBitmapImage(string filePath)
|
||||||
|
{
|
||||||
|
//Icon ico;
|
||||||
|
//BitmapImage bmpImage = null;
|
||||||
|
//MemoryStream strm;
|
||||||
|
//using (ico = GetIcon(filePath))
|
||||||
|
//{
|
||||||
|
// Bitmap bmp = ico.ToBitmap();
|
||||||
|
// using (strm = new MemoryStream())
|
||||||
|
// {
|
||||||
|
// bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png);
|
||||||
|
// bmpImage = new BitmapImage();
|
||||||
|
// bmpImage.BeginInit();
|
||||||
|
// strm.Seek(0, SeekOrigin.Begin);
|
||||||
|
// bmpImage.StreamSource = strm;
|
||||||
|
// bmpImage.EndInit();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//return bmpImage;
|
||||||
|
Icon ico = GetIcon(filePath);
|
||||||
|
Bitmap bmp = ico.ToBitmap();
|
||||||
|
MemoryStream strm = new MemoryStream();
|
||||||
|
bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png);
|
||||||
|
BitmapImage bmpImage = new BitmapImage();
|
||||||
|
bmpImage.BeginInit();
|
||||||
|
strm.Seek(0, SeekOrigin.Begin);
|
||||||
|
bmpImage.StreamSource = strm;
|
||||||
|
bmpImage.EndInit();
|
||||||
|
|
||||||
|
return bmpImage.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetIconIndex(string pszFile)
|
||||||
|
{
|
||||||
|
SHFILEINFO sfi = new SHFILEINFO();
|
||||||
|
Shell32.SHGetFileInfo(pszFile
|
||||||
|
, 0
|
||||||
|
, ref sfi
|
||||||
|
, (uint)System.Runtime.InteropServices.Marshal.SizeOf(sfi)
|
||||||
|
, (uint)(SHGFI.SysIconIndex | SHGFI.LargeIcon | SHGFI.UseFileAttributes));
|
||||||
|
return sfi.iIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 256*256
|
||||||
|
public static IntPtr GetJumboIcon(int iImage)
|
||||||
|
{
|
||||||
|
IImageList spiml = null;
|
||||||
|
Guid guil = new Guid(IID_IImageList2);//or IID_IImageList
|
||||||
|
|
||||||
|
Shell32.SHGetImageList(Shell32.SHIL_JUMBO, ref guil, ref spiml);
|
||||||
|
IntPtr hIcon = IntPtr.Zero;
|
||||||
|
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon);
|
||||||
|
|
||||||
|
return hIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
|
||||||
|
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";
|
||||||
|
|
||||||
|
public static class Shell32
|
||||||
|
{
|
||||||
|
|
||||||
|
public const int SHIL_LARGE = 0x0;
|
||||||
|
public const int SHIL_SMALL = 0x1;
|
||||||
|
public const int SHIL_EXTRALARGE = 0x2;
|
||||||
|
public const int SHIL_SYSSMALL = 0x3;
|
||||||
|
public const int SHIL_JUMBO = 0x4;
|
||||||
|
public const int SHIL_LAST = 0x4;
|
||||||
|
|
||||||
|
public const int ILD_TRANSPARENT = 0x00000001;
|
||||||
|
public const int ILD_IMAGE = 0x00000020;
|
||||||
|
|
||||||
|
[DllImport("shell32.dll", EntryPoint = "#727")]
|
||||||
|
public extern static int SHGetImageList(int iImageList, ref Guid riid, ref IImageList ppv);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", EntryPoint = "DestroyIcon", SetLastError = true)]
|
||||||
|
public static unsafe extern int DestroyIcon(IntPtr hIcon);
|
||||||
|
|
||||||
|
[DllImport("shell32.dll")]
|
||||||
|
public static extern uint SHGetIDListFromObject([MarshalAs(UnmanagedType.IUnknown)] object iUnknown, out IntPtr ppidl);
|
||||||
|
|
||||||
|
[DllImport("Shell32.dll")]
|
||||||
|
public static extern IntPtr SHGetFileInfo(
|
||||||
|
string pszPath,
|
||||||
|
uint dwFileAttributes,
|
||||||
|
ref SHFILEINFO psfi,
|
||||||
|
uint cbFileInfo,
|
||||||
|
uint uFlags
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum SHGFI : uint
|
||||||
|
{
|
||||||
|
/// <summary>get icon</summary>
|
||||||
|
Icon = 0x000000100,
|
||||||
|
/// <summary>get display name</summary>
|
||||||
|
DisplayName = 0x000000200,
|
||||||
|
/// <summary>get type name</summary>
|
||||||
|
TypeName = 0x000000400,
|
||||||
|
/// <summary>get attributes</summary>
|
||||||
|
Attributes = 0x000000800,
|
||||||
|
/// <summary>get icon location</summary>
|
||||||
|
IconLocation = 0x000001000,
|
||||||
|
/// <summary>return exe type</summary>
|
||||||
|
ExeType = 0x000002000,
|
||||||
|
/// <summary>get system icon index</summary>
|
||||||
|
SysIconIndex = 0x000004000,
|
||||||
|
/// <summary>put a link overlay on icon</summary>
|
||||||
|
LinkOverlay = 0x000008000,
|
||||||
|
/// <summary>show icon in selected state</summary>
|
||||||
|
Selected = 0x000010000,
|
||||||
|
/// <summary>get only specified attributes</summary>
|
||||||
|
Attr_Specified = 0x000020000,
|
||||||
|
/// <summary>get large icon</summary>
|
||||||
|
LargeIcon = 0x000000000,
|
||||||
|
/// <summary>get small icon</summary>
|
||||||
|
SmallIcon = 0x000000001,
|
||||||
|
/// <summary>get open icon</summary>
|
||||||
|
OpenIcon = 0x000000002,
|
||||||
|
/// <summary>get shell size icon</summary>
|
||||||
|
ShellIconSize = 0x000000004,
|
||||||
|
/// <summary>pszPath is a pidl</summary>
|
||||||
|
PIDL = 0x000000008,
|
||||||
|
/// <summary>use passed dwFileAttribute</summary>
|
||||||
|
UseFileAttributes = 0x000000010,
|
||||||
|
/// <summary>apply the appropriate overlays</summary>
|
||||||
|
AddOverlays = 0x000000020,
|
||||||
|
/// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
|
||||||
|
OverlayIndex = 0x000000040,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct SHFILEINFO
|
||||||
|
{
|
||||||
|
public const int NAMESIZE = 80;
|
||||||
|
public IntPtr hIcon;
|
||||||
|
public int iIcon;
|
||||||
|
public uint dwAttributes;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||||
|
public string szDisplayName;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||||
|
public string szTypeName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct RECT
|
||||||
|
{
|
||||||
|
public int left, top, right, bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct POINT
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct IMAGELISTDRAWPARAMS
|
||||||
|
{
|
||||||
|
public int cbSize;
|
||||||
|
public IntPtr himl;
|
||||||
|
public int i;
|
||||||
|
public IntPtr hdcDst;
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int cx;
|
||||||
|
public int cy;
|
||||||
|
public int xBitmap; // x offest from the upperleft of bitmap
|
||||||
|
public int yBitmap; // y offset from the upperleft of bitmap
|
||||||
|
public int rgbBk;
|
||||||
|
public int rgbFg;
|
||||||
|
public int fStyle;
|
||||||
|
public int dwRop;
|
||||||
|
public int fState;
|
||||||
|
public int Frame;
|
||||||
|
public int crEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct IMAGEINFO
|
||||||
|
{
|
||||||
|
public IntPtr hbmImage;
|
||||||
|
public IntPtr hbmMask;
|
||||||
|
public int Unused1;
|
||||||
|
public int Unused2;
|
||||||
|
public RECT rcImage;
|
||||||
|
}
|
||||||
|
[ComImportAttribute()]
|
||||||
|
[GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
|
||||||
|
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
public interface IImageList
|
||||||
|
{
|
||||||
|
[PreserveSig]
|
||||||
|
int Add(
|
||||||
|
IntPtr hbmImage,
|
||||||
|
IntPtr hbmMask,
|
||||||
|
ref int pi);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int ReplaceIcon(
|
||||||
|
int i,
|
||||||
|
IntPtr hicon,
|
||||||
|
ref int pi);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetOverlayImage(
|
||||||
|
int iImage,
|
||||||
|
int iOverlay);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Replace(
|
||||||
|
int i,
|
||||||
|
IntPtr hbmImage,
|
||||||
|
IntPtr hbmMask);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int AddMasked(
|
||||||
|
IntPtr hbmImage,
|
||||||
|
int crMask,
|
||||||
|
ref int pi);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Draw(
|
||||||
|
ref IMAGELISTDRAWPARAMS pimldp);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Remove(int i);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetIcon(
|
||||||
|
int i,
|
||||||
|
int flags,
|
||||||
|
ref IntPtr picon);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetImageInfo(
|
||||||
|
int i,
|
||||||
|
ref IMAGEINFO pImageInfo);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Copy(
|
||||||
|
int iDst,
|
||||||
|
IImageList punkSrc,
|
||||||
|
int iSrc,
|
||||||
|
int uFlags);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Merge(
|
||||||
|
int i1,
|
||||||
|
IImageList punk2,
|
||||||
|
int i2,
|
||||||
|
int dx,
|
||||||
|
int dy,
|
||||||
|
ref Guid riid,
|
||||||
|
ref IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int Clone(
|
||||||
|
ref Guid riid,
|
||||||
|
ref IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetImageRect(
|
||||||
|
int i,
|
||||||
|
ref RECT prc);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetIconSize(
|
||||||
|
ref int cx,
|
||||||
|
ref int cy);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetIconSize(
|
||||||
|
int cx,
|
||||||
|
int cy);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetImageCount(ref int pi);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetImageCount(
|
||||||
|
int uNewCount);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetBkColor(
|
||||||
|
int clrBk,
|
||||||
|
ref int pclr);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetBkColor(
|
||||||
|
ref int pclr);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int BeginDrag(
|
||||||
|
int iTrack,
|
||||||
|
int dxHotspot,
|
||||||
|
int dyHotspot);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int EndDrag();
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int DragEnter(
|
||||||
|
IntPtr hwndLock,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int DragLeave(
|
||||||
|
IntPtr hwndLock);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int DragMove(
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetDragCursorImage(
|
||||||
|
ref IImageList punk,
|
||||||
|
int iDrag,
|
||||||
|
int dxHotspot,
|
||||||
|
int dyHotspot);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int DragShowNolock(
|
||||||
|
int fShow);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetDragImage(
|
||||||
|
ref POINT ppt,
|
||||||
|
ref POINT pptHotspot,
|
||||||
|
ref Guid riid,
|
||||||
|
ref IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetItemFlags(
|
||||||
|
int i,
|
||||||
|
ref int dwFlags);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetOverlayImage(
|
||||||
|
int iOverlay,
|
||||||
|
ref int piIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
864
Util/ListViewDragDropManager.cs
Normal file
864
Util/ListViewDragDropManager.cs
Normal file
@@ -0,0 +1,864 @@
|
|||||||
|
// 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 WPF.JoshSmith.Adorners;
|
||||||
|
using WPF.JoshSmith.Controls.Utilities;
|
||||||
|
|
||||||
|
namespace WPF.JoshSmith.ServiceProviders.UI
|
||||||
|
{
|
||||||
|
#region ListViewDragDropManager
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages the dragging and dropping of ListViewItems in a ListView.
|
||||||
|
/// The ItemType type parameter indicates the type of the objects in
|
||||||
|
/// the ListView's items source. The ListView'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 ListView's items.</typeparam>
|
||||||
|
public class ListViewDragDropManager<ItemType> where ItemType : class
|
||||||
|
{
|
||||||
|
#region Data
|
||||||
|
|
||||||
|
bool canInitiateDrag;
|
||||||
|
DragAdorner dragAdorner;
|
||||||
|
double dragAdornerOpacity;
|
||||||
|
int indexToSelect;
|
||||||
|
bool isDragInProgress;
|
||||||
|
ItemType itemUnderDragCursor;
|
||||||
|
ListView listView;
|
||||||
|
Point ptMouseDown;
|
||||||
|
bool showDragAdorner;
|
||||||
|
|
||||||
|
#endregion // Data
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of ListViewDragManager.
|
||||||
|
/// </summary>
|
||||||
|
public ListViewDragDropManager()
|
||||||
|
{
|
||||||
|
this.canInitiateDrag = false;
|
||||||
|
this.dragAdornerOpacity = 0.7;
|
||||||
|
this.indexToSelect = -1;
|
||||||
|
this.showDragAdorner = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of ListViewDragManager.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="listView"></param>
|
||||||
|
public ListViewDragDropManager( ListView listView )
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
this.ListView = listView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of ListViewDragManager.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="listView"></param>
|
||||||
|
/// <param name="dragAdornerOpacity"></param>
|
||||||
|
public ListViewDragDropManager( ListView listView, double dragAdornerOpacity )
|
||||||
|
: this( listView )
|
||||||
|
{
|
||||||
|
this.DragAdornerOpacity = dragAdornerOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of ListViewDragManager.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="listView"></param>
|
||||||
|
/// <param name="showDragAdorner"></param>
|
||||||
|
public ListViewDragDropManager( ListView listView, bool showDragAdorner )
|
||||||
|
: this( listView )
|
||||||
|
{
|
||||||
|
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 ListView
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/sets the ListView whose dragging is managed. This property
|
||||||
|
/// can be set to null, to prevent drag management from occuring. If
|
||||||
|
/// the ListView's AllowDrop property is false, it will be set to true.
|
||||||
|
/// </summary>
|
||||||
|
public ListView ListView
|
||||||
|
{
|
||||||
|
get { return listView; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if( this.IsDragInProgress )
|
||||||
|
throw new InvalidOperationException( "Cannot set the ListView property during a drag operation." );
|
||||||
|
|
||||||
|
if( this.listView != null )
|
||||||
|
{
|
||||||
|
#region Unhook Events
|
||||||
|
|
||||||
|
this.listView.PreviewMouseLeftButtonDown -= listView_PreviewMouseLeftButtonDown;
|
||||||
|
this.listView.PreviewMouseMove -= listView_PreviewMouseMove;
|
||||||
|
this.listView.DragOver -= listView_DragOver;
|
||||||
|
this.listView.DragLeave -= listView_DragLeave;
|
||||||
|
this.listView.DragEnter -= listView_DragEnter;
|
||||||
|
this.listView.Drop -= listView_Drop;
|
||||||
|
|
||||||
|
#endregion // Unhook Events
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listView = value;
|
||||||
|
|
||||||
|
if( this.listView != null )
|
||||||
|
{
|
||||||
|
if( !this.listView.AllowDrop )
|
||||||
|
this.listView.AllowDrop = true;
|
||||||
|
|
||||||
|
#region Hook Events
|
||||||
|
|
||||||
|
this.listView.PreviewMouseLeftButtonDown += listView_PreviewMouseLeftButtonDown;
|
||||||
|
this.listView.PreviewMouseMove += listView_PreviewMouseMove;
|
||||||
|
this.listView.DragOver += listView_DragOver;
|
||||||
|
this.listView.DragLeave += listView_DragLeave;
|
||||||
|
this.listView.DragEnter += listView_DragEnter;
|
||||||
|
this.listView.Drop += listView_Drop;
|
||||||
|
|
||||||
|
#endregion // Hook Events
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // ListView
|
||||||
|
|
||||||
|
#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 ListViewItem 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 listView_PreviewMouseLeftButtonDown
|
||||||
|
|
||||||
|
void listView_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 ListViewItem the user clicked on for later.
|
||||||
|
this.ptMouseDown = MouseUtilities.GetMousePosition( this.listView );
|
||||||
|
this.indexToSelect = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ptMouseDown = new Point( -10000, -10000 );
|
||||||
|
this.indexToSelect = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // listView_PreviewMouseLeftButtonDown
|
||||||
|
|
||||||
|
#region listView_PreviewMouseMove
|
||||||
|
|
||||||
|
void listView_PreviewMouseMove( object sender, MouseEventArgs e )
|
||||||
|
{
|
||||||
|
if( !this.CanStartDragOperation )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Select the item the user clicked on.
|
||||||
|
if( this.listView.SelectedIndex != this.indexToSelect )
|
||||||
|
this.listView.SelectedIndex = this.indexToSelect;
|
||||||
|
|
||||||
|
// If the item at the selected index is null, there's nothing
|
||||||
|
// we can do, so just return;
|
||||||
|
if( this.listView.SelectedItem == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
ListViewItem itemToDrag = this.GetListViewItem( this.listView.SelectedIndex );
|
||||||
|
if( itemToDrag == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
AdornerLayer adornerLayer = this.ShowDragAdornerResolved ? this.InitializeAdornerLayer( itemToDrag ) : null;
|
||||||
|
|
||||||
|
this.InitializeDragOperation( itemToDrag );
|
||||||
|
this.PerformDragOperation();
|
||||||
|
this.FinishDragOperation( itemToDrag, adornerLayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // listView_PreviewMouseMove
|
||||||
|
|
||||||
|
#region listView_DragOver
|
||||||
|
|
||||||
|
void listView_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.ListView.Items[index] as ItemType;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // listView_DragOver
|
||||||
|
|
||||||
|
#region listView_DragLeave
|
||||||
|
|
||||||
|
void listView_DragLeave( object sender, DragEventArgs e )
|
||||||
|
{
|
||||||
|
if( !this.IsMouseOver( this.listView ) )
|
||||||
|
{
|
||||||
|
if( this.ItemUnderDragCursor != null )
|
||||||
|
this.ItemUnderDragCursor = null;
|
||||||
|
|
||||||
|
if( this.dragAdorner != null )
|
||||||
|
this.dragAdorner.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // listView_DragLeave
|
||||||
|
|
||||||
|
#region listView_DragEnter
|
||||||
|
|
||||||
|
void listView_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 // listView_DragEnter
|
||||||
|
|
||||||
|
#region listView_Drop
|
||||||
|
|
||||||
|
void listView_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.listView.ItemsSource as ObservableCollection<ItemType>;
|
||||||
|
if( itemsSource == null )
|
||||||
|
throw new Exception(
|
||||||
|
"A ListView managed by ListViewDragManager 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 ListView 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 ListView 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 ListView into
|
||||||
|
// our ListView, 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 );
|
||||||
|
else
|
||||||
|
itemsSource.Insert( newIndex, data );
|
||||||
|
|
||||||
|
// Set the Effects property so that the call to DoDragDrop will return 'Move'.
|
||||||
|
e.Effects = DragDropEffects.Move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // listView_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( ListViewItem draggedItem, AdornerLayer adornerLayer )
|
||||||
|
{
|
||||||
|
// Let the ListViewItem know that it is not being dragged anymore.
|
||||||
|
ListViewItemDragState.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 GetListViewItem
|
||||||
|
|
||||||
|
ListViewItem GetListViewItem( int index )
|
||||||
|
{
|
||||||
|
if( this.listView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.listView.ItemContainerGenerator.ContainerFromIndex( index ) as ListViewItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListViewItem GetListViewItem( ItemType dataItem )
|
||||||
|
{
|
||||||
|
if( this.listView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.listView.ItemContainerGenerator.ContainerFromItem( dataItem ) as ListViewItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // GetListViewItem
|
||||||
|
|
||||||
|
#region HasCursorLeftDragThreshold
|
||||||
|
|
||||||
|
bool HasCursorLeftDragThreshold
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if( this.indexToSelect < 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ListViewItem item = this.GetListViewItem( this.indexToSelect );
|
||||||
|
Rect bounds = VisualTreeHelper.GetDescendantBounds( item );
|
||||||
|
Point ptInItem = this.listView.TranslatePoint( this.ptMouseDown, item );
|
||||||
|
|
||||||
|
// In case the cursor is at the very top or bottom of the ListViewItem
|
||||||
|
// 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 ptInListView = MouseUtilities.GetMousePosition( this.listView );
|
||||||
|
return !rect.Contains( ptInListView );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // HasCursorLeftDragThreshold
|
||||||
|
|
||||||
|
#region IndexUnderDragCursor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the index of the ListViewItem 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.listView.Items.Count; ++i )
|
||||||
|
{
|
||||||
|
ListViewItem item = this.GetListViewItem( i );
|
||||||
|
if( this.IsMouseOver( item ) )
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // IndexUnderDragCursor
|
||||||
|
|
||||||
|
#region InitializeAdornerLayer
|
||||||
|
|
||||||
|
AdornerLayer InitializeAdornerLayer( ListViewItem itemToDrag )
|
||||||
|
{
|
||||||
|
// Create a brush which will paint the ListViewItem 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.listView, itemToDrag.RenderSize, brush );
|
||||||
|
|
||||||
|
// Set the drag adorner's opacity.
|
||||||
|
this.dragAdorner.Opacity = this.DragAdornerOpacity;
|
||||||
|
|
||||||
|
AdornerLayer layer = AdornerLayer.GetAdornerLayer( this.listView );
|
||||||
|
layer.Add( dragAdorner );
|
||||||
|
|
||||||
|
// Save the location of the cursor when the left mouse button was pressed.
|
||||||
|
this.ptMouseDown = MouseUtilities.GetMousePosition( this.listView );
|
||||||
|
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // InitializeAdornerLayer
|
||||||
|
|
||||||
|
#region InitializeDragOperation
|
||||||
|
|
||||||
|
void InitializeDragOperation( ListViewItem itemToDrag )
|
||||||
|
{
|
||||||
|
// Set some flags used during the drag operation.
|
||||||
|
this.IsDragInProgress = true;
|
||||||
|
this.canInitiateDrag = false;
|
||||||
|
|
||||||
|
// Let the ListViewItem know that it is being dragged.
|
||||||
|
ListViewItemDragState.SetIsBeingDragged( itemToDrag, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // InitializeDragOperation
|
||||||
|
|
||||||
|
#region IsMouseOver
|
||||||
|
|
||||||
|
bool IsMouseOver( Visual target )
|
||||||
|
{
|
||||||
|
// We need to use MouseUtilities 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 = MouseUtilities.GetMousePosition( target );
|
||||||
|
return bounds.Contains( mousePos );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // IsMouseOver
|
||||||
|
|
||||||
|
#region IsMouseOverScrollbar
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the mouse cursor is over a scrollbar in the ListView.
|
||||||
|
/// </summary>
|
||||||
|
bool IsMouseOverScrollbar
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Point ptMouse = MouseUtilities.GetMousePosition( this.listView );
|
||||||
|
HitTestResult res = VisualTreeHelper.HitTest( this.listView, 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 )
|
||||||
|
{
|
||||||
|
ListViewItem listViewItem = this.GetListViewItem( this.itemUnderDragCursor );
|
||||||
|
if( listViewItem != null )
|
||||||
|
ListViewItemDragState.SetIsUnderDragCursor( listViewItem, i == 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // ItemUnderDragCursor
|
||||||
|
|
||||||
|
#region PerformDragOperation
|
||||||
|
|
||||||
|
void PerformDragOperation()
|
||||||
|
{
|
||||||
|
ItemType selectedItem = this.listView.SelectedItem as ItemType;
|
||||||
|
DragDropEffects allowedEffects = DragDropEffects.Move | DragDropEffects.Move | DragDropEffects.Link;
|
||||||
|
if( DragDrop.DoDragDrop( this.listView, selectedItem, allowedEffects ) != DragDropEffects.None )
|
||||||
|
{
|
||||||
|
// The item was dropped into a new location,
|
||||||
|
// so make it the new selected item.
|
||||||
|
this.listView.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 = MouseUtilities.GetMousePosition( this.ListView );
|
||||||
|
|
||||||
|
double left = ptCursor.X - this.ptMouseDown.X;
|
||||||
|
|
||||||
|
// 4/13/2007 - Made the top offset relative to the item being dragged.
|
||||||
|
ListViewItem itemBeingDragged = this.GetListViewItem( this.indexToSelect );
|
||||||
|
Point itemLoc = itemBeingDragged.TranslatePoint( new Point( 0, 0 ), this.ListView );
|
||||||
|
double top = itemLoc.Y + ptCursor.Y - this.ptMouseDown.Y;
|
||||||
|
|
||||||
|
this.dragAdorner.SetOffsets( left, top );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // UpdateDragAdornerLocation
|
||||||
|
|
||||||
|
#endregion // Private Helpers
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // ListViewDragDropManager
|
||||||
|
|
||||||
|
#region ListViewItemDragState
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exposes attached properties used in conjunction with the ListViewDragDropManager class.
|
||||||
|
/// Those properties can be used to allow triggers to modify the appearance of ListViewItems
|
||||||
|
/// in a ListView during a drag-drop operation.
|
||||||
|
/// </summary>
|
||||||
|
public static class ListViewItemDragState
|
||||||
|
{
|
||||||
|
#region IsBeingDragged
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the ListViewItemDragState's IsBeingDragged attached property.
|
||||||
|
/// This field is read-only.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsBeingDraggedProperty =
|
||||||
|
DependencyProperty.RegisterAttached(
|
||||||
|
"IsBeingDragged",
|
||||||
|
typeof( bool ),
|
||||||
|
typeof( ListViewItemDragState ),
|
||||||
|
new UIPropertyMetadata( false ) );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the specified ListViewItem is being dragged, else false.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The ListViewItem to check.</param>
|
||||||
|
public static bool GetIsBeingDragged( ListViewItem item )
|
||||||
|
{
|
||||||
|
return (bool)item.GetValue( IsBeingDraggedProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the IsBeingDragged attached property for the specified ListViewItem.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The ListViewItem to set the property on.</param>
|
||||||
|
/// <param name="value">Pass true if the element is being dragged, else false.</param>
|
||||||
|
internal static void SetIsBeingDragged( ListViewItem item, bool value )
|
||||||
|
{
|
||||||
|
item.SetValue( IsBeingDraggedProperty, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // IsBeingDragged
|
||||||
|
|
||||||
|
#region IsUnderDragCursor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies the ListViewItemDragState's IsUnderDragCursor attached property.
|
||||||
|
/// This field is read-only.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsUnderDragCursorProperty =
|
||||||
|
DependencyProperty.RegisterAttached(
|
||||||
|
"IsUnderDragCursor",
|
||||||
|
typeof( bool ),
|
||||||
|
typeof( ListViewItemDragState ),
|
||||||
|
new UIPropertyMetadata( false ) );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the specified ListViewItem is currently underneath the cursor
|
||||||
|
/// during a drag-drop operation, else false.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The ListViewItem to check.</param>
|
||||||
|
public static bool GetIsUnderDragCursor( ListViewItem item )
|
||||||
|
{
|
||||||
|
return (bool)item.GetValue( IsUnderDragCursorProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the IsUnderDragCursor attached property for the specified ListViewItem.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The ListViewItem 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( ListViewItem item, bool value )
|
||||||
|
{
|
||||||
|
item.SetValue( IsUnderDragCursorProperty, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // IsUnderDragCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // ListViewItemDragState
|
||||||
|
|
||||||
|
#region ProcessDropEventArgs
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event arguments used by the ListViewDragDropManager.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 ListView 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
|
||||||
|
}
|
||||||
29
Util/MenuWidthConvert.cs
Normal file
29
Util/MenuWidthConvert.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace GeekDesk.Util
|
||||||
|
{
|
||||||
|
class MenuWidthConvert : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value != null && value.ToString().Length>0)
|
||||||
|
{
|
||||||
|
return System.Convert.ToDouble(value.ToString()) - 10d;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Util/MouseUtilities.cs
Normal file
58
Util/MouseUtilities.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace WPF.JoshSmith.Controls.Utilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to the mouse location by calling unmanaged code.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This class was written by Dan Crevier (Microsoft).
|
||||||
|
/// http://blogs.msdn.com/llobo/archive/2006/09/06/Scrolling-Scrollviewer-on-Mouse-Drag-at-the-boundaries.aspx
|
||||||
|
/// </remarks>
|
||||||
|
public class MouseUtilities
|
||||||
|
{
|
||||||
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
|
private struct Win32Point
|
||||||
|
{
|
||||||
|
public Int32 X;
|
||||||
|
public Int32 Y;
|
||||||
|
};
|
||||||
|
|
||||||
|
[DllImport( "user32.dll" )]
|
||||||
|
private static extern bool GetCursorPos( ref Win32Point pt );
|
||||||
|
|
||||||
|
[DllImport( "user32.dll" )]
|
||||||
|
private static extern bool ScreenToClient( IntPtr hwnd, ref Win32Point pt );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the mouse cursor location. This method is necessary during
|
||||||
|
/// a drag-drop operation because the WPF mechanisms for retrieving the
|
||||||
|
/// cursor coordinates are unreliable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativeTo">The Visual to which the mouse coordinates will be relative.</param>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
152
Util/SystemIcon.cs
Normal file
152
Util/SystemIcon.cs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Drawing;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using GeekDesk.Util;
|
||||||
|
|
||||||
|
namespace GeekDesk.Util
|
||||||
|
{
|
||||||
|
class SystemIcon
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||||
|
public struct SHFILEINFO
|
||||||
|
{
|
||||||
|
public IntPtr hIcon;
|
||||||
|
public int iIcon;
|
||||||
|
public uint dwAttributes;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||||
|
public string szDisplayName;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||||
|
public string szTypeName;
|
||||||
|
}
|
||||||
|
[DllImport("Shell32.dll", EntryPoint = "SHGetFileInfo", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
|
||||||
|
[DllImport("User32.dll", EntryPoint = "DestroyIcon")]
|
||||||
|
public static extern int DestroyIcon(IntPtr hIcon);
|
||||||
|
#region API 参数的常量定义
|
||||||
|
public enum FileInfoFlags : uint
|
||||||
|
{
|
||||||
|
SHGFI_ICON = 0x000000100, // get icon
|
||||||
|
SHGFI_DISPLAYNAME = 0x000000200, // get display name
|
||||||
|
SHGFI_TYPENAME = 0x000000400, // get type name
|
||||||
|
SHGFI_ATTRIBUTES = 0x000000800, // get attributes
|
||||||
|
SHGFI_ICONLOCATION = 0x000001000, // get icon location
|
||||||
|
SHGFI_EXETYPE = 0x000002000, // return exe type
|
||||||
|
SHGFI_SYSICONINDEX = 0x000004000, // get system icon index
|
||||||
|
SHGFI_LINKOVERLAY = 0x000008000, // put a link overlay on icon
|
||||||
|
SHGFI_SELECTED = 0x000010000, // show icon in selected state
|
||||||
|
SHGFI_ATTR_SPECIFIED = 0x000020000, // get only specified attributes
|
||||||
|
SHGFI_LARGEICON = 0x000000000, // get large icon
|
||||||
|
SHGFI_SMALLICON = 0x000000001, // get small icon
|
||||||
|
SHGFI_OPENICON = 0x000000002, // get open icon
|
||||||
|
SHGFI_SHELLICONSIZE = 0x000000004, // get shell size icon
|
||||||
|
SHGFI_PIDL = 0x000000008, // pszPath is a pidl
|
||||||
|
SHGFI_USEFILEATTRIBUTES = 0x000000010, // use passed dwFileAttribute
|
||||||
|
SHGFI_ADDOVERLAYS = 0x000000020, // apply the appropriate overlays
|
||||||
|
SHGFI_OVERLAYINDEX = 0x000000040 // Get the index of the overlay
|
||||||
|
}
|
||||||
|
public enum FileAttributeFlags : uint
|
||||||
|
{
|
||||||
|
FILE_ATTRIBUTE_READONLY = 0x00000001,
|
||||||
|
FILE_ATTRIBUTE_HIDDEN = 0x00000002,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM = 0x00000004,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
|
||||||
|
FILE_ATTRIBUTE_DEVICE = 0x00000040,
|
||||||
|
FILE_ATTRIBUTE_NORMAL = 0x00000080,
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
|
||||||
|
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
|
||||||
|
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
|
||||||
|
FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
|
||||||
|
FILE_ATTRIBUTE_OFFLINE = 0x00001000,
|
||||||
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
|
||||||
|
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
/// <summary>
|
||||||
|
/// 获取文件类型的关联图标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName">文件类型的扩展名或文件的绝对路径</param>
|
||||||
|
/// <param name="isLargeIcon">是否返回大图标</param>
|
||||||
|
/// <returns>获取到的图标</returns>
|
||||||
|
public static Icon GetIcon(string fileName, bool isLargeIcon)
|
||||||
|
{
|
||||||
|
//SHFILEINFO shfi = new SHFILEINFO();
|
||||||
|
//IntPtr hI;
|
||||||
|
//if (isLargeIcon)
|
||||||
|
// hI = SHGetFileInfo(fileName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), (uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (uint)FileInfoFlags.SHGFI_LARGEICON);
|
||||||
|
//else
|
||||||
|
// hI = SHGetFileInfo(fileName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), (uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (uint)FileInfoFlags.SHGFI_SMALLICON);
|
||||||
|
//Icon icon = Icon.FromHandle(shfi.hIcon).Clone() as Icon;
|
||||||
|
//DestroyIcon(shfi.hIcon); //释放资源
|
||||||
|
|
||||||
|
//选中文件中的图标总数
|
||||||
|
//var iconTotalCount = PrivateExtractIcons(fileName, 0, 0, 0, null, null, 1, 0);
|
||||||
|
//用于接收获取到的图标指针
|
||||||
|
//IntPtr[] hIcons = new IntPtr[1];
|
||||||
|
////对应的图标id
|
||||||
|
//int[] ids = new int[1];
|
||||||
|
////成功获取到的图标个数
|
||||||
|
//int successCount = PrivateExtractIcons(fileName, 0, 0, 0, hIcons, ids, 1, 0);
|
||||||
|
//Icon ico = Icon.FromHandle(hIcons[0]);
|
||||||
|
//var myIcon = ico.ToBitmap();
|
||||||
|
//myIcon.Save("D:\\" + ids[0].ToString("000") + ".png", ImageFormat.Png);
|
||||||
|
IntPtr hIcon = FileIcon.GetJumboIcon(FileIcon.GetIconIndex(fileName));
|
||||||
|
//IntPtr hIcon = GetJumboIcon(GetIconIndex("*." + ext));
|
||||||
|
|
||||||
|
// from native to managed
|
||||||
|
Icon ico = Icon.FromHandle(hIcon);
|
||||||
|
string path = "D:\\test\\" + System.Guid.NewGuid().ToString() + ".png";
|
||||||
|
//using ( ico = (Icon)Icon.FromHandle(hIcon).Clone())
|
||||||
|
//{
|
||||||
|
// // save to file (or show in a picture box)
|
||||||
|
// ico.ToBitmap().Save(path, ImageFormat.Png);
|
||||||
|
//}
|
||||||
|
//FileIcon.Shell32.DestroyIcon(hIcon); // don't forget to cleanup
|
||||||
|
|
||||||
|
return ico;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 获取文件夹图标
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>图标</returns>
|
||||||
|
public static Icon GetDirectoryIcon(bool isLargeIcon)
|
||||||
|
{
|
||||||
|
SHFILEINFO _SHFILEINFO = new SHFILEINFO();
|
||||||
|
IntPtr _IconIntPtr;
|
||||||
|
if (isLargeIcon)
|
||||||
|
{
|
||||||
|
_IconIntPtr = SHGetFileInfo(@"", 0, ref _SHFILEINFO, (uint)Marshal.SizeOf(_SHFILEINFO), ((uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_LARGEICON));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_IconIntPtr = SHGetFileInfo(@"", 0, ref _SHFILEINFO, (uint)Marshal.SizeOf(_SHFILEINFO), ((uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_SMALLICON));
|
||||||
|
}
|
||||||
|
if (_IconIntPtr.Equals(IntPtr.Zero)) return null;
|
||||||
|
Icon _Icon = System.Drawing.Icon.FromHandle(_SHFILEINFO.hIcon);
|
||||||
|
return _Icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("User32.dll")]
|
||||||
|
public static extern int PrivateExtractIcons(
|
||||||
|
string lpszFile, //file name
|
||||||
|
int nIconIndex, //The zero-based index of the first icon to extract.
|
||||||
|
int cxIcon, //The horizontal icon size wanted.
|
||||||
|
int cyIcon, //The vertical icon size wanted.
|
||||||
|
IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
|
||||||
|
int[] piconid, //(out) A pointer to a returned resource identifier.
|
||||||
|
int nIcons, //The number of icons to extract from the file. Only valid when *.exe and *.dll
|
||||||
|
int flags //Specifies flags that control this function.
|
||||||
|
);
|
||||||
|
|
||||||
|
//[DllImport("User32.dll")]
|
||||||
|
//public static extern bool DestroyIcon(
|
||||||
|
// IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
88
ViewModel/AppConfig.cs
Normal file
88
ViewModel/AppConfig.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
using GalaSoft.MvvmLight;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GeekDesk.Constant;
|
||||||
|
|
||||||
|
namespace GeekDesk.ViewModel
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class AppConfig : ViewModelBase
|
||||||
|
{
|
||||||
|
private int menuSortType = (int)SortType.CUSTOM; //菜单排序类型
|
||||||
|
private int iconSortType = (int)SortType.CUSTOM; //图表排序类型
|
||||||
|
private double windowWidth = (double)DefaultConstant.WINDOW_WIDTH; //窗口宽度
|
||||||
|
private double windowHeight = (double)DefaultConstant.WINDOW_HEIGHT; //窗口高度
|
||||||
|
private double menuCardWidth = (double)DefaultConstant.MENU_CARD_WIDHT;//菜单栏宽度
|
||||||
|
|
||||||
|
|
||||||
|
#region GetSet
|
||||||
|
public int MenuSortType {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return menuSortType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
menuSortType = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IconSortType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return iconSortType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
iconSortType = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double WindowWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return windowWidth;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
windowWidth = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double WindowHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return windowHeight;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
windowHeight = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double MenuCardWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return menuCardWidth;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
menuCardWidth = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
70
ViewModel/DataInfos.cs
Normal file
70
ViewModel/DataInfos.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using GalaSoft.MvvmLight;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace GeekDesk.ViewModel
|
||||||
|
{
|
||||||
|
public class DataInfos : ViewModelBase
|
||||||
|
{
|
||||||
|
private string path; //路径
|
||||||
|
private string name; //文件名
|
||||||
|
private int count = 0; //打开次数
|
||||||
|
private BitmapImage bitmapImage; //位图
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
count = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
name = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
path = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapImage BitmapImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return bitmapImage;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
bitmapImage = value;
|
||||||
|
RaisePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
ViewModel/MainModel.cs
Normal file
12
ViewModel/MainModel.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GeekDesk.ViewModel
|
||||||
|
{
|
||||||
|
class MainModel
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
34
ViewModel/MainViewModel.cs
Normal file
34
ViewModel/MainViewModel.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using GalaSoft.MvvmLight;
|
||||||
|
|
||||||
|
namespace GeekDesk.ViewModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class contains properties that the main View can data bind to.
|
||||||
|
/// <para>
|
||||||
|
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// You can also use Blend to data bind with the tool's support.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// See http://www.galasoft.ch/mvvm
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public class MainViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the MainViewModel class.
|
||||||
|
/// </summary>
|
||||||
|
public MainViewModel()
|
||||||
|
{
|
||||||
|
////if (IsInDesignMode)
|
||||||
|
////{
|
||||||
|
//// // Code runs in Blend --> create design time data.
|
||||||
|
////}
|
||||||
|
////else
|
||||||
|
////{
|
||||||
|
//// // Code runs "for real"
|
||||||
|
////}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
ViewModel/MenuViewModel.cs
Normal file
36
ViewModel/MenuViewModel.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GeekDesk.ViewModel
|
||||||
|
{
|
||||||
|
class MenuViewModel
|
||||||
|
{
|
||||||
|
|
||||||
|
public MenuViewModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<Menu> GetMenus()
|
||||||
|
{
|
||||||
|
ObservableCollection<Menu> menus = new ObservableCollection<Menu>();
|
||||||
|
menus.Add(new Menu() { menu = "test1" });
|
||||||
|
menus.Add(new Menu() { menu = "test2" });
|
||||||
|
menus.Add(new Menu() { menu = "test3" });
|
||||||
|
return menus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Menu
|
||||||
|
{
|
||||||
|
public string menu { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
packages.config
Normal file
9
packages.config
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="CommonServiceLocator" version="2.0.6" targetFramework="net452" requireReinstallation="true" />
|
||||||
|
<package id="HandyControl" version="3.1.0" targetFramework="net452" requireReinstallation="true" />
|
||||||
|
<package id="MvvmLight" version="5.4.1.1" targetFramework="net452" />
|
||||||
|
<package id="MvvmLightLibs" version="5.4.1.1" targetFramework="net452" />
|
||||||
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||||
|
<package id="System.Drawing.Common" version="5.0.2" targetFramework="net472" />
|
||||||
|
</packages>
|
||||||
Reference in New Issue
Block a user