Rx DragBehavior -> Почему мой элемент не движется - PullRequest
1 голос
/ 31 марта 2011

Я написал DragBehavior на основе общих примеров Drag and Drop. Хотя это работает без поведения, оно не движется, когда я помещаю код в поведение.

Поведение:

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>

Ответы [ 2 ]

3 голосов
/ 01 апреля 2011

Измените шаблон немного ... мб это вам поможет ..

<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>
2 голосов
/ 01 апреля 2011

Код на самом деле работает?Добавьте точку останова «Когда попал» в OnAttached и ваше закрытие подписки, чтобы отследить, что происходит на самом деле

Кроме того, несколько замечаний о вашей реализации:

  • Я бы рекомендовал создать1006 * private member и присваивает возвращаемое значение Subscribe его Disposable свойству.Это позволит вам отписаться от всего в OnDetached
  • Нет необходимости выбирать позицию события MouseUp, поскольку TakeUntil не требует, чтобы последовательности были одного типа.

Редактировать: Думаю, проблема в том, что StackPanel, к которому вы добавляете свойства Canvas, на самом деле является дочерним элементом элемента ItemContainerTemplate (ContentPresenter), а не Canvasсам.Вы должны либо пройтись по дереву в методе поведения OnAttached, либо определить свой собственный ItemContainerTemplate и вместо этого присоединить поведение к ContentPresenter.

...