我根据一般的拖放示例编写了一个DragBehavior。虽然这可以在不使用行为的情况下工作,但是当我将代码置于行为中时它不会移动。
行为:
public class DragBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
Window mainCanvas = Application.Current.MainWindow;
var mouseDown = from evt in AssociatedObject.GetMouseLeftButtonDown()
select evt.EventArgs.GetPosition(mainCanvas);
var mouseUp = from evt in AssociatedObject.GetMouseLeftButtonUp()
select evt.EventArgs.GetPosition(mainCanvas);
var mouseMove = from evt in AssociatedObject.GetMouseMove()
select evt.EventArgs.GetPosition(mainCanvas);
var q = from start in mouseDown
from delta in mouseMove.StartWith(start).TakeUntil(mouseUp)
.Let(mm => mm.Zip(mm.Skip(1),(pre,cur) =>
new{ X= cur.X - pre.X, Y= cur.Y - pre.Y}))
select delta;
q.Subscribe(value =>
{
Canvas.SetLeft(AssociatedObject, Canvas.GetLeft(AssociatedObject) + value.X);
Canvas.SetTop(AssociatedObject, Canvas.GetTop(AssociatedObject) + value.Y);
});
}
}
帮助方法:
public static IObservable<IEvent<MouseEventArgs>> GetMouseMove(
this UIElement inputElement)
{
return Observable.FromEvent(
(EventHandler<MouseEventArgs> h) => new MouseEventHandler(h),
h => inputElement.MouseMove += h,
h => inputElement.MouseMove -= h);
}
public static IObservable<IEvent<MouseButtonEventArgs>>
GetMouseLeftButtonDown(this UIElement inputElement)
{
return Observable.FromEvent(
(EventHandler<MouseButtonEventArgs> genericHandler) =>
new MouseButtonEventHandler(genericHandler),
h => inputElement.MouseLeftButtonDown += (h),
h => inputElement.MouseLeftButtonDown -= (h));
}
public static IObservable<IEvent<MouseButtonEventArgs>>
GetMouseLeftButtonUp(this UIElement inputElement)
{
return Observable.FromEvent(
(EventHandler<MouseButtonEventArgs> genericHandler) =>
new MouseButtonEventHandler(genericHandler),
h => inputElement.MouseLeftButtonUp += h,
h => inputElement.MouseLeftButtonUp -= h);
}}
<Window x:Class="DesignerTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:DesignerTest.ViewModels"
xmlns:h="clr-namespace:DesignerTest.Helpers"
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:WindowViewModel />
</Window.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Path=Shapes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<e:Interaction.Behaviors>
<h:DragBehavior />
</e:Interaction.Behaviors>
<TextBlock Text="{Binding X}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X,Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y,Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
答案 0 :(得分:3)
稍微改变你的模板......这对你有帮助..
<DataTemplate>
<!-- change background to transparent -->
<StackPanel Background="Transparent">
<e:Interaction.Behaviors>
<h:DragBehavior />
</e:Interaction.Behaviors>
<!-- Prevent yout textBlock from capturing mouse events -->
<!-- by setting is HitTestVisible to false -->
<TextBlock Text="{Binding X}" IsHitTestVisible="False" />
</StackPanel>
</DataTemplate>
答案 1 :(得分:2)
代码是否实际运行?向OnAttached添加“When Hit”断点,并在Subscribe闭包中找出正在发生的事情
另外,有关您实施的一些注意事项:
MutableDisposable
私有成员,并将Subscribe
的返回值分配给它的Disposable
属性。这样您就可以取消订阅OnDetached
TakeUntil
不要求序列属于同一类型。 编辑:我认为问题在于您添加Canvas属性的StackPanel
实际上是ItemContainerTemplate
(ContentPresenter
)元素的子元素而不是Canvas
本身。您应该在行为的OnAttached
方法中走树,或者定义自己的ItemContainerTemplate
并将行为附加到ContentPresenter
。