I wrote a DragBehavior based on the general Drag and Drop examples. While this is working without being in a Behavior, it is not moving when I place the code in a behavior.
Behavior:
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);
});
}
}
Helper Methods:
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>
</ItemsC开发者_C百科ontrol.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>
Change your template a little... mb this will help you..
<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>
Is the code actually running? Add a "When Hit" breakpoint to OnAttached and your Subscribe closure to trace out what's atually happening
Also, a few notes on your implementation:
- I'd recommend creating a
MutableDisposableprivate member and assigning the return value ofSubscribeto it'sDisposableproperty. This will allow you to unsubscribe from everything inOnDetached - There's no need to select the MouseUp event's position as
TakeUntildoesn't require that the sequences be of the same type.
Edit: I think the problem is that the StackPanel you are adding the Canvas properties to is actually the child of the ItemContainerTemplate (ContentPresenter) element, not of the Canvas itself. You should either walk the tree in the behavior's OnAttached method, or define your own ItemContainerTemplate and attach the behavior to the ContentPresenter instead.
加载中,请稍侯......
精彩评论