Fir*_*oso 2 .net c# wpf draggable attachedbehaviors
所以这是我正在使用的场景:
我有一个当前表示为ItemsControl/ListView的优先级列表,绑定到可观察的优先级项集合.我想为元素重新排序提供严格视觉上受约束的垂直拖动.
所以,没有拖拽装饰,没有水平移动,只有垂直移动.当列表项移过另一个项的中点时,它应该通过动画"交换位置".我确信这可以通过在容器本身上使用mousedown/mousemove来完成,我确信可以应用渲染转换来执行此操作,但我理想的解决方案将包含两个组件:
该功能可以作为WPF交互行为附加.
该系统将是MVVM友好的,不需要任何重要的代码.
这已经完成了吗?我在哪里可以找到它?如果没有,我怎么能把所有的位放在一起才能做到这一点?
编辑:赏金开了.请通过评论直接向我提问,我会尽快回复.
对于代码......
加价:
<AdornerDecorator Margin="5">
<ListBox x:Name="_listBox" Width="300"
HorizontalAlignment="Left"
ItemsSource="{Binding Path=Items}"
AllowDrop="True" Drop="listBox_Drop">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="ListBoxItem.DragOver" Handler="listBoxItem_DragOver"/>
<EventSetter Event="ListBoxItem.Drop" Handler="listBoxItem_Drop"/>
<EventSetter Event="ListBoxItem.MouseMove" Handler="listBoxItem_MouseMove"/>
<EventSetter Event="ListBoxItem.MouseDown" Handler="listBoxItem_MouseDown"/>
<EventSetter Event="ListBoxItem.PreviewMouseDown" Handler="listBoxItem_MouseDown"/>
<Setter Property="AllowDrop" Value="True"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</AdornerDecorator>
Run Code Online (Sandbox Code Playgroud)
代码隐藏:
private bool _isDragging;
private void listBox_MouseDown(object sender, MouseButtonEventArgs e)
{
_isDragging = false;
}
Adorner _adorner;
private void listBox_MouseMove(object sender, MouseEventArgs e)
{
if (!_isDragging && e.LeftButton == MouseButtonState.Pressed)
{
_isDragging = true;
if (_listBox.SelectedValue != null)
{
DragDrop.DoDragDrop(_listBox, _listBox.SelectedValue,
DragDropEffects.Move);
}
}
}
private ListBoxItem FindlistBoxItem(DragEventArgs e)
{
var visualHitTest = VisualTreeHelper.HitTest(_listBox, e.GetPosition(_listBox)).VisualHit;
ListBoxItem listBoxItem = null;
while (visualHitTest != null)
{
if (visualHitTest is ListBoxItem)
{
listBoxItem = visualHitTest as ListBoxItem;
break;
}
else if (visualHitTest == _listBox)
{
Console.WriteLine("Found listBox instance");
return null;
}
visualHitTest = VisualTreeHelper.GetParent(visualHitTest);
}
return listBoxItem;
}
void ClearAdorner()
{
if (_adorner != null)
{
var adornerLayer = AdornerLayer.GetAdornerLayer(_listBox);
adornerLayer.Remove(_adorner);
}
}
private void listBox_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Move;
ClearAdorner();
var listBoxItem = FindlistBoxItem(e);
if (listBoxItem == null || listBoxItem.DataContext == _listBox.SelectedItem) return;
if (IsInFirstHalf(listBoxItem, e.GetPosition(listBoxItem)))
{
var adornerLayer = AdornerLayer.GetAdornerLayer(_listBox);
_adorner = new DropBeforeAdorner(listBoxItem);
adornerLayer.Add(_adorner);
}
else if (IsInLastHalf(listBoxItem, e.GetPosition(listBoxItem)))
{
var adornerLayer = AdornerLayer.GetAdornerLayer(_listBox);
_adorner = new DropAfterAdorner(listBoxItem);
adornerLayer.Add(_adorner);
}
}
private void listBox_Drop(object sender, DragEventArgs e)
{
if (_isDragging)
{
_isDragging = false;
ClearAdorner();
var listBoxItem = FindlistBoxItem(e);
if (listBoxItem == null || listBoxItem.DataContext == _listBox.SelectedItem) return;
var drop = _listBox.SelectedItem as Export.Domain.Components.Component;
var target = listBoxItem.DataContext as Export.Domain.Components.Component;
var listBoxItem = GetlistBoxItemControl(listBoxItem);
if (IsInFirstHalf(listBoxItem, e.GetPosition(listBoxItem)))
{
var vm = this.DataContext as ComponentlistBoxModel;
vm.DropBefore(drop, target);
}
else if (IsInLastHalf(listBoxItem, e.GetPosition(listBoxItem)))
{
var vm = this.DataContext as ComponentlistBoxModel;
vm.DropAfter(drop, target);
}
}
}
public static bool IsInFirstHalf(FrameworkElement container, Point mousePosition)
{
return mousePosition.Y < (container.ActualHeight/2);
}
public static bool IsInLastHalf(FrameworkElement container, Point mousePosition)
{
return mousePosition.Y > (container.ActualHeight/2);
}
Run Code Online (Sandbox Code Playgroud)
您可能不喜欢我的代码隐藏具体地按类型引用viewmodel的事实,但它完成了工作,并且它快速而简单,并且从技术上讲它不会破坏MVVM模式.我仍然将逻辑留给viewmodel.
增加1 动画可能会提供您正在寻找的效果.在我的实现中,交换发生在drop.但是,您可以通过使用装饰器并在拖动时进行交换来实现动画效果.拖动事件将更新装饰位置和集合中对象的索引.
| 归档时间: |
|
| 查看次数: |
2064 次 |
| 最近记录: |