void SetItemsInViewModelColumns(ObservableCollection <ColumnViewModel> columns) { Dictionary <object, ColumnViewModel> quickColumnsFromId = new Dictionary <object, ColumnViewModel>(); Dictionary <object, IEnumerable <ItemViewModel> > listFromId = new Dictionary <object, IEnumerable <ItemViewModel> >(); ObservableCollection <ItemViewModel> remainingItems = new ObservableCollection <ItemViewModel>(); ColumnViewModel unclassifiedColumn = null; foreach (ColumnViewModel column in columns) { column.UnalteredItemsCollection.Clear(); if (column.ColumnDefinition.Id != null) { quickColumnsFromId.Add(column.ColumnDefinition.Id, column); listFromId.Add(column.ColumnDefinition.Id, new ObservableCollection <ItemViewModel>()); } else { unclassifiedColumn = column; unclassifiedColumn.IsUnclassifiedColumn = true; } } if (ItemsSource != null) { foreach (Object item in ItemsSource) { //Get the id from the item and add a Binding to it so we can update it when necessary: object id; ItemViewModel itemViewModel = new ItemViewModel(item, this); Binding binding = new Binding(ColumnMemberPath); binding.Source = item; binding.Mode = BindingMode.TwoWay; BindingOperations.SetBinding(itemViewModel, ItemViewModel.ItemColumnIdProperty, binding); //itemViewModel.SetBinding(ItemViewModel.ItemColumnIdProperty, binding); id = itemViewModel.ItemColumnId; //todo: handle the case where the Binding is broken. //Add a binging to get the ItemOrder: Binding orderBinding = new Binding(OrderMemberPath); orderBinding.Source = item; orderBinding.Mode = BindingMode.TwoWay; BindingOperations.SetBinding(itemViewModel, ItemViewModel.ItemOrderProperty, orderBinding); //itemViewModel.SetBinding(ItemViewModel.ItemOrderProperty, orderBinding); //Add the item to the list for the corresponding id: if (id != null && listFromId.ContainsKey(id)) { ((ObservableCollection <ItemViewModel>)listFromId[id]).Add(itemViewModel); } else { remainingItems.Add(itemViewModel); } } foreach (object id in listFromId.Keys) { quickColumnsFromId[id].UnalteredItemsCollection = (ObservableCollection <ItemViewModel>)listFromId[id]; } if (unclassifiedColumn != null) { //we should always enter this "if" unclassifiedColumn.UnalteredItemsCollection = remainingItems; } } }
public void Execute(object parameter) { //Version using Drop event: var param = parameter as System.Windows.DragEventArgs; if (param != null) { var castedParameter = param.Data.GetData("ItemDragEventArgs") as ItemDragEventArgs; int newItemOrder = -1; //We get the item on which the element was dropped: var elements = VisualTreeHelper.FindElementsInHostCoordinates(param.GetPosition(null).Position, _column.ColumnDefinition._kanBanControl); FrameworkElement elementDroppedOn = elements.ElementAt(0) as FrameworkElement; while (elementDroppedOn != null && //we go up the visual tree until we reached the root or... (elementDroppedOn.DataContext == null || elementDroppedOn.DataContext.GetType() != typeof(ItemViewModel))) //...until we found an element that has the ItemViewModel as DataContext { elementDroppedOn = elementDroppedOn.Parent as FrameworkElement; } if (elementDroppedOn != null) { //todo: find a way to know in which half of the DropElement the dragged element was dropped. // We could do with comparing the position at which it was dropped with the position of the root of the item card // (but it need us to find said root - could be done by going up the visual tree until we find an element whose DataContext is not an ItemViewModel // -> the last one with the ItemViewModel should be the root element) // We could try to know it the cursor was on the Header or the body of the card. //for now, we will consider the element dropped above: newItemOrder = ((ItemViewModel)elementDroppedOn.DataContext).ItemOrder + 1; //Reminder: we have chosen to have the items with the bigger order number higher on the displayed list. } //Version using ItemDragCompleted event (this one doesn't seem good because the sender is the column from which the item comes): //var castedParameter = parameter as ItemDragEventArgs; //if(castedParameter != null) //{ SelectionCollection selectionCollection = castedParameter.Data as SelectionCollection; if (selectionCollection.Count > 0) { Selection selection = selectionCollection.ElementAt(0); //we can only drag one item so it is at the position 0. FrameworkElement container = selection.Item as FrameworkElement; ItemViewModel itemViewModel = container.DataContext as ItemViewModel; if (itemViewModel != null) { itemViewModel.ItemOrder = newItemOrder; UpdateItemOrders(newItemOrder); itemViewModel.ItemColumnId = _column.ColumnDefinition.Id; //force a refresh of the KanBanControl: //todo: find a way to only refresh the Column itself. var kanBanControl = _column.ColumnDefinition._kanBanControl; var columns = kanBanControl.Columns; kanBanControl.Columns = null; kanBanControl.Columns = columns; // Raise the "ItemMoved" event: kanBanControl.OnItemMoved(itemViewModel); //keep the following to only refresh the column itself. It cannot be used properly currently as it causes a bug where the items are duplicated. ////refresh the elements of the column: //_column.Dispatcher.BeginInvoke( () => //{ // _column.UnalteredItemsCollection.Add(itemViewModel); //we add the item manually because the whole collection was not refreshed in the process. This should change with Smooth refresh. // _column.SetOrderedItemsCollection(); // }); //_column.SetOrderedItemsCollection(); } } } }