Использование MouseDragElementBehavior с ItemsControl и Canvas

В настоящее время у меня возникла проблема с использованием MouseDragElementsBehavior из Blend SDK при использовании ItemsControl и Custom Canvas. Мой пользовательский холст просто добавляет или удаляет MouseDragElement из его дочерних элементов в зависимости от DependencyProperty. Это работало просто отлично, когда я вручную добавлял элементы к дочерним элементам Canvas, но, похоже, сломался при переходе к ItemsControl.

В настоящее время я использую следующий код ItemsControl:

<ItemsControl ItemsSource="{Binding Path=CanvasItems}">
  <ItemsControl.DataContext>
    <ViewModels:ViewModel/>
  </ItemsControl.DataContext>
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <my:CustomCanvas Background="Black" IsEditable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CanEdit}" AllowDrop="{Binding RelativeSource={RelativeSource Self}, Path=IsEditable}"  />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>

Добавление поведения перетаскивания в метод Canvas.VisualChildrenChanged не позволяет перемещать вновь созданный объект, как раньше.

Нужно ли добавлять поведение Drag к чему-то другому, кроме ContentPresenter, который передается VisualChildrenChanged, или предоставлять специальный стиль?


person JMcCarty    schedule 15.06.2011    source источник


Ответы (1)


Я действительно не знаю поведения blend sdk, но я работал с поведением в целом, поэтому я надеюсь, что применимы те же механизмы.

Если вы хотите добавить поведение к элементам управления, созданным ItemsControl, лучше всего добавить его с помощью установщика в ItemsControl.ItemContainerStyle, хотя в этом случае мне было проще добавить его в ItemsControl.ItemTemplate.

Что-то вроде

        <ItemsControl ItemsSource="{Binding CanvasItems}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Background="Transparent" AllowDrop="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Green" BorderThickness="1" Background="AntiqueWhite">
                        <i:Interaction.Behaviors>
                            <ei:MouseDragElementBehavior ConstrainToParentBounds="True" DragBegun="MouseDragElementBehavior_DragBegun"/>
                        </i:Interaction.Behaviors>
                        <ContentControl Content="{Binding}" />
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
person Jörg Reichardt    schedule 15.06.2011
comment
Это сработало бы, если бы я выполнял перетаскивание (уже реализовано)... DragMouseElement используется для перемещения объекта в его контейнере. - person JMcCarty; 15.06.2011
comment
К сожалению, у меня нет Blend, поэтому я не могу протестировать код. Но я все же предполагаю, что MouseDragElementBehaviour изменит присоединенное свойство Canvas.X элемента управления, к которому он был прикреплен, поэтому он все равно должен работать. Стиль контейнера элементов применяется ко всем контейнерам, сгенерированным ItemsControl. Я отредактировал код, чтобы отразить образцы поведения смешивания, которые я видел. - person Jörg Reichardt; 15.06.2011
comment
Предоставленный вами стиль приводит к ошибке несоответствия количества параметров. Вы случайно не помните, где вы видели эти образцы, чтобы я мог взглянуть? - person JMcCarty; 15.06.2011
comment
Образец был intertech.com/Blog/post/Blend-Behaviors. -Are-Good.aspx, но это не очень полезно для вашей проблемы. У меня была синтаксическая ошибка в моем коде, теги должны быть Setter.Value, а не просто Value. Я исправил это. Не могли бы вы опубликовать код вашего Canvas.VisualChildrenChanged, чтобы я мог лучше понять, как работает поведение? - person Jörg Reichardt; 16.06.2011
comment
Только что загрузил blend sdk и увидел, что Interaction.Behaviors доступен только для чтения, поэтому мое решение все равно не будет работать. попробую найти другое решение - person Jörg Reichardt; 16.06.2011
comment
Я отказался от полного ItemsContainerStyle и теперь использовал ItemTemplate. Ему не хватает элегантности и он более многословен, но, похоже, он работает. Я до сих пор не совсем уверен, как это должно себя вести, но, по крайней мере, я достигаю обработчика события DragBegun, как только начал перетаскивать границу. Оттуда вы можете изменить прикрепленное свойство Canvas.X отправителя или что-то в этом роде. Если вы не хотите, чтобы граница и ваши элементы уже имели непрозрачную, перетаскиваемую форму, просто переместите поведение с границы на ContentControl. - person Jörg Reichardt; 16.06.2011