Allowing drag and drop when you use VariableSizeWrapGrid- By default drag and drop and reordering of items are available when you not use variablesizewrapGrid in GridView. If you tend to use variableSizeWrapGrid and still want to use Drag/Drop and Re-Ordering you might use the below extensionClass
///
/// The class implements drag&drop for cases which are not supported by the control:
/// - for ItemsPanels other than StackPanel, WrapGrid, VirtualizingStackPanel;
/// - for cases when grouping is set.
/// It also allows adding new groups to the underlying datasource if end-user drags some item to the left-most or the rigt-most sides of the control.
///
/// ///
/// The
/// - for ItemsPanels other than StackPanel, WrapGrid, VirtualizingStackPanel;
/// - for cases when grouping is set.
/// It also allows adding new groups to the underlying datasource if end-user drags some item to the left-most or the rigt-most sides of the control.
///
/// To allow new group creation by the end-user, set
/// To add new group, handle
/// property value defines whether the new group creation has been requested by the end-user actions.
/// If this property is true, create the new data group and insert it into the groups collection at the positions, specified by the
///
/// into the newly added group.
/// Note: you should create new group from your code, as the
///
[TemplatePart(Name = DraggableGridView.NewGroupPlaceHolderFirstName, Type = typeof(FrameworkElement))]
[TemplatePart(Name = DraggableGridView.NewGroupPlaceHolderLastName, Type = typeof(FrameworkElement))]
[TemplatePart(Name = DraggableGridView.ScrollViewerName, Type = typeof(ScrollViewer))]
public partial class DraggableGridView : GridView
{
//-------------------------------------------------------------
#region ** Template Parts
private const string NewGroupPlaceHolderFirstName = "NewGroupPlaceHolderFirst";
private FrameworkElement _newGroupPlaceHolderFirst;
private const string NewGroupPlaceHolderLastName = "NewGroupPlaceHolderLast";
private FrameworkElement _newGroupPlaceHolderLast;
private const string ScrollViewerName = "ScrollViewer";
private ScrollViewer _scrollViewer;
#endregion ** Template Parts
//----------------------------------------------------------------------
#region ** dependency properties
///
/// Gets or sets the
/// This is a dependency property. The default value is false.
///
public bool AllowNewGroup
{
get { return (bool)GetValue(AllowNewGroupProperty); }
set { SetValue(AllowNewGroupProperty, value); }
}
///
/// Identifies the
///
public static readonly DependencyProperty AllowNewGroupProperty =
DependencyProperty.Register("AllowNewGroup", typeof(bool), typeof(GridViewCustomControl), new PropertyMetadata(false));
#endregion ** dependency properties
//----------------------------------------------------------------------
#region ** events
///
/// Occurs before performing drop operation,
///
public event EventHandler
///
/// Rizes the
///
/// Event data for the event.
protected virtual void OnBeforeDrop(BeforeDropItemsEventArgs e)
{
if (null != BeforeDrop)
{
BeforeDrop(this, e);
}
}
#endregion ** events
//----------------------------------------------------------------------
#region ** fields
protected int _lastIndex = 0; // index of the currently dragged item
private int _currentOverIndex = -1; // index which should be used if we drop immediately
private int _topReorderHintIndex = -1; // index of element which has been moved up (need it to restore item visual state later)
private int _bottomReorderHintIndex = -1; // index of element which has been moved down (need it to restore item visual state later)
private int _lastGroup = -1; // index of the currently dragged item group
private int _currentOverGroup = -1; // index of the group under the pointer
#endregion ** fields
//----------------------------------------------------------------------
#region ** ctor & initialization
///
/// Initializes a new instance of the
///
public DraggableGridView()
{
CanReorderItems = true;
AllowDrop = true;
CanDragItems = true;
this.DragItemsStarting += GridViewEx_DragItemsStarting;
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
_newGroupPlaceHolderFirst = GetTemplateChild(NewGroupPlaceHolderFirstName) as FrameworkElement;
_newGroupPlaceHolderLast = GetTemplateChild(NewGroupPlaceHolderLastName) as FrameworkElement;
_scrollViewer = GetTemplateChild(ScrollViewerName) as ScrollViewer;
}
#endregion ** ctor & initialization
//----------------------------------------------------------------------
#region ** protected
///
/// Stores dragged items into DragEventArgs.Data.Properties["Items"] value.
/// Override this method to set custom drag data if you need to.
///
///
protected virtual void OnDragStarting(DragItemsStartingEventArgs e)
{
e.Data.RequestedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;
e.Data.Properties.Add("Items", e.Items);
// set some custom drag data as below
// e.Data.SetText(_lastIndex.ToString());
}
///
/// Handles drag&drop for cases when it is not supported by the Windows.UI.Xaml.Controls.GridView control (for example, for grouped GridView).
///
///
protected override async void OnDrop(DragEventArgs e)
{
//IList
//object item = (items != null && items.Count > 0) ? items[0] : Items[_lastIndex];
//if (items != null)
//{
// // read custom drag data as below if they have been set in OnDragStarting
// // string text = await e.Data.GetView().GetTextAsync();
// int newIndex = GetDragOverIndex(e);
// var oldIndex = this.Items.IndexOf(item);
// if (newIndex != oldIndex)
// {
// //var oldItem = this.Items[newIndex];
// //this.Items.RemoveAt(newIndex);
// //this.Items.RemoveAt(oldIndex-1);
// //this.Items.Insert(newIndex, item);
// //this.Items.Insert(oldIndex, oldItem);
// this.Items.Clear();
// this.Items.Add(item);
// }
//}
// base.OnDrop(e);
}
///
/// Shows reoder hints while custom dragging.
///
///
protected override void OnDragOver(DragEventArgs e)
{
/* set ReorderHintStates for underlying items
* possible ReorderHintStates:
- "NoReorderHint"
- "BottomReorderHint"
- "TopReorderHint"
- "RightReorderHint"
- "LeftReorderHint"
*/
IList
//object item = (items != null && items.Count > 0) ? items[0] : Items[_lastIndex];
if (items != null)/*This code make sure if items are dragging over in sections while dropping we don't need to show reorder hint here*/
{
int newIndex = GetDragOverIndex(e);
if (newIndex >= 0 && _currentOverIndex != newIndex)
{
_currentOverIndex = newIndex;
if (_topReorderHintIndex != -1)
{
GoItemToState(_topReorderHintIndex, "NoReorderHint", true);
_topReorderHintIndex = -1;
}
if (_bottomReorderHintIndex != -1)
{
GoItemToState(_bottomReorderHintIndex, "NoReorderHint", true);
_bottomReorderHintIndex = -1;
}
if (newIndex > 0)
{
_topReorderHintIndex = newIndex - 1;
}
if (newIndex < Items.Count)
{
_bottomReorderHintIndex = newIndex;
}
if (IsGrouping && _currentOverGroup >= 0)
{
int topHintGroup = GetGroupForIndex(_topReorderHintIndex);
if (topHintGroup != _currentOverGroup)
{
_topReorderHintIndex = -1;
}
int bottomHintGroup = GetGroupForIndex(_bottomReorderHintIndex);
if (bottomHintGroup != _currentOverGroup)
{
_bottomReorderHintIndex = -1;
}
}
if (_topReorderHintIndex >= 0)
{
GoItemToState(_topReorderHintIndex, "TopReorderHint", true);
}
if (_bottomReorderHintIndex >= 0)
{
GoItemToState(_bottomReorderHintIndex, "BottomReorderHint", true);
}
}
}
base.OnDragOver(e);
}
#endregion ** protected
//----------------------------------------------------------------------
#region ** private
private void GridViewEx_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
_currentOverIndex = -1;
_topReorderHintIndex = -1;
_bottomReorderHintIndex = -1;
_lastGroup = -1;
_currentOverGroup = -1;
object item = e.Items[0];
_lastIndex = this.ItemContainerGenerator.IndexFromContainer(this.ItemContainerGenerator.ContainerFromItem(item));
_lastGroup = this.GetItemGroup(item);
OnDragStarting(e);
}
protected int GetDragOverIndex(DragEventArgs e)
{
FrameworkElement root = Window.Current.Content as FrameworkElement;
Point position = this.TransformToVisual(root).TransformPoint(e.GetPosition(this));
int newIndex = -1;
// check items directly under the pointer
foreach (var element in VisualTreeHelper.FindElementsInHostCoordinates(position, root))
{
// assume horizontal orientation
var container = element as ContentControl;
if (container == null)
{
continue;
}
int tempIndex = this.ItemContainerGenerator.IndexFromContainer(container);
if (tempIndex >= 0)
{
_currentOverGroup = GetItemGroup(container.Content);
// we only need GridViewItems belonging to this GridView control
// if we found one - we done
newIndex = tempIndex;
// adjust index depending on pointer position
Point center = container.TransformToVisual(root).TransformPoint(new Point(container.ActualWidth / 2, container.ActualHeight / 2));
if (position.Y > center.Y)
{
newIndex++;
}
break;
}
}
if (newIndex < 0)
{
// if we haven't found item under the pointer, check items in the rectangle to the left from the pointer position
foreach (var element in GetIntersectingItems(position, root))
{
// assume horizontal orientation
var container = element as ContentControl;
if (container == null)
{
continue;
}
int tempIndex = this.ItemContainerGenerator.IndexFromContainer(container);
if (tempIndex < 0)
{
// we only need GridViewItems belonging to this GridView control
// so skip all elements which are not
continue;
}
Rect bounds = container.TransformToVisual(root).TransformBounds(new Rect(0, 0, container.ActualWidth, container.ActualHeight));
if (bounds.Left <= position.X && bounds.Top <= position.Y && tempIndex > newIndex)
{
_currentOverGroup = GetItemGroup(container.Content);
newIndex = tempIndex;
// adjust index depending on pointer position
if (position.Y > bounds.Top + container.ActualHeight / 2)
{
newIndex++;
}
if (bounds.Right > position.X && bounds.Bottom > position.Y)
{
break;
}
}
}
}
if (newIndex < 0)
{
newIndex = 0;
}
if (newIndex >= Items.Count)
{
newIndex = Items.Count - 1;
}
return newIndex;
}
///
/// returns all items in the rectangle with x=0, y=0, width=intersectingPoint.X, height=root.ActualHeight.
///
///
///
///
private static IEnumerable
{
Rect rect = new Rect(0, 0, intersectingPoint.X, root.ActualHeight);
return VisualTreeHelper.FindElementsInHostCoordinates(rect, root);
}
private void GoItemToState(int index, string state, bool useTransitions)
{
if (index >= 0)
{
Control control = this.ItemContainerGenerator.ContainerFromIndex(index) as Control;
if (control != null)
{
VisualStateManager.GoToState(control, state, useTransitions);
}
}
}
private int GetGroupForIndex(int index)
{
if (index < 0)
{
return index;
}
return GetItemGroup(Items[index]);
}
private int GetItemGroup(object item)
{
ICollectionView view = this.ItemsSource as ICollectionView;
if (view != null && view.CollectionGroups != null)
{
foreach (ICollectionViewGroup gr in view.CollectionGroups)
{
if (gr.Group == item || gr.GroupItems.IndexOf(item) >= 0)
{
return view.CollectionGroups.IndexOf(gr);
}
}
}
return -1;
}
#endregion ** private
}
///
/// Provides data for the
///
public sealed class BeforeDropItemsEventArgs : System.ComponentModel.CancelEventArgs
{
internal BeforeDropItemsEventArgs(object item, int oldIndex, int newIndex, DragEventArgs dragEventArgs)
: this(item, oldIndex, newIndex, -1, -1, false, dragEventArgs)
{
}
internal BeforeDropItemsEventArgs(object item, int oldIndex, int newIndex,
int oldGroupIndex, int newGroupIndex, bool requestCreateNewGroup, DragEventArgs dragEventArgs)
: base()
{
RequestCreateNewGroup = requestCreateNewGroup;
OldGroupIndex = oldGroupIndex;
NewGroupIndex = newGroupIndex;
OldIndex = oldIndex;
NewIndex = newIndex;
Item = item;
}
///
/// Gets the item which is beeing dragged.
///
public object Item
{
get;
private set;
}
///
/// Gets the current item index in the underlying data source.
///
public int OldIndex
{
get;
private set;
}
///
/// Gets the index in the underlying data source where the item will be insertet by the drop operation.
///
public int NewIndex
{
get;
private set;
}
///
/// Gets the
/// This property only makes sense if GridViewEx.IsGrouping property is true.
///
///
/// If this property is true, create the new data group and insert it into the groups collection at the positions, specified by the
///
/// into the newly added group.
///
public bool RequestCreateNewGroup
{
get;
internal set;
}
///
/// Gets the current item data group index in the underlying data source.
/// This property only makes sense if GridViewEx.IsGrouping property is true.
///
public int OldGroupIndex
{
get;
internal set;
}
///
/// Gets the data group index in the underlying data source where the item will be insertet by the drop operation.
/// This property only makes sense if GridViewEx.IsGrouping property is true.
///
public int NewGroupIndex
{
get;
internal set;
}
///
/// Gets the original
///
public DragEventArgs DragEventArgs
{
get;
private set;
}
}
}
After that you can handle the DropMethod in your any of derived calsses like below
public class DraggableSectionGridView : DraggableGridView
{
public DraggableSectionGridView()
{
this.Drop += DraggableSectionGridView_Drop;
}
private ObservableCollection
{
get { return this.ItemsSource as ObservableCollection
}
void DraggableSectionGridView_Drop(object sender, Windows.UI.Xaml.DragEventArgs e)
{
//throw new NotImplementedException();
IList
object draggedItem = (items != null && items.Count > 0) ? items[0] : Items[_lastIndex];
if (items != null)
{
// read custom drag data as below if they have been set in OnDragStarting
// string text = await e.Data.GetView().GetTextAsync();
int droppedIndex = GetDragOverIndex(e);
var draggedIndex = this.ItemsSourceValue.IndexOf(draggedItem as GridViewCustomControl);
if (droppedIndex >= 0 && draggedIndex >= 0)
{
if (droppedIndex != draggedIndex)
{
var droppedItem = this.ItemsSourceValue[droppedIndex];
this.ItemsSourceValue.RemoveAt(draggedIndex);
if (droppedIndex > draggedIndex)
{
//this.Items.RemoveAt(oldIndex);
droppedIndex -= 1;
//oldIndex += 1;
}
//var freshDraggedControl = Activator.CreateInstance(draggedItem.GetType()) as GridViewCustomControl;
this.ItemsSourceValue.Insert(droppedIndex, draggedItem as GridViewCustomControl);
//freshDraggedControl.DataContext = (draggedItem as Control).DataContext;
}
}
}
}
}
Feel free to reach me by posting comment or emailing me vinod8812@gmail.com
No comments:
Post a Comment
Send us your comment related to the topic mentioned on the blog