Silverlight:如何在Canvas中的ItemsControl中移动项目

时间:2011-12-17 12:09:36

标签: silverlight silverlight-4.0 canvas itemscontrol

我有一个ItemsControl,它将UserControl显示为ItemTemplate。它有一个Canvas ItemsPanel。

   <ItemsControl ItemsSource="{Binding Path=MyItems}" Margin="200,20,0,0">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:MyControl Margin="10,10,10,10"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Height="2000" Width="2000"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

我想在鼠标拖动上移动Canvas上的控件

MyControl有一个行为:

<UserControl x:Class="MyControl">

    <StackPanel x:Name="LayoutRoot" >
        <Grid Background="LightBlue" Height="20">
    </StackPanel>
<Interactivity:Interaction.Behaviors>
    <Behavior:DragControlBehavior />
</Interactivity:Interaction.Behaviors>
</UserControl>

DragControlBehavior通过控件

在MouseMove上设置Canvas附加属性

[更新] - 以下是行为的完整源代码

public class DragControlBehavior : Behavior<MyControl>
{
    private DependencyObject _parent;
    private bool _isMouseCaptured = false;

    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += (sender, e) =>
        {
            _isMouseCaptured = true;
        };

        AssociatedObject.MouseLeftButtonUp += (sender, e) =>
        {
            _isMouseCaptured = false;
        };

        AssociatedObject.MouseMove += (sender, e) =>
        {
            if (_isMouseCaptured)
            {
                if (_parent == null)
                {
                    _parent = VisualTreeHelper.GetParent(AssociatedObject);
                    while (_parent.GetType() != typeof(Canvas))
                        _parent = VisualTreeHelper.GetParent(_parent);
                }
                var pointOnCanvas = e.GetPosition((Canvas)_parent);
                Canvas.SetTop(AssociatedObject, pointOnCanvas.Y);
                Canvas.SetLeft(AssociatedObject, pointOnCanvas.X);
            }
        };
    }

如果我在Canvas上单独使用MyControl的实例,它可以工作,但如果ItemsControl中有MyControls集合,则它们不会在MouseMove上移动

在WPF中,我会使用ItemContainerStyle但在SL中它不可用:

        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                <Setter Property="Canvas.Top" Value="{Binding Top}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>

1 个答案:

答案 0 :(得分:1)

当您使用ItemsControl时,生成的每个项目都会包含在ContentPresenter中。可视化树看起来有点像:

System.Windows.Controls.ItemsControl
  System.Windows.Controls.ItemsPresenter
    System.Windows.Controls.Canvas
      System.Windows.Controls.ContentPresenter
        DragControlBehaviorTest.MyControl
          ...

DragControlBehaviorTest是我为试用你的代码而创建的项目的名称。)

Canvas.LeftCanvas.Top附加属性仅适用于Canvas的直接子项。如果您将MyControl直接放在Canvas中,则MyControlCanvas的孩子,因此设置Canvas.LeftCanvas.Top它会起作用。但是,如果您使用ItemsControl生成MyControl s,ContentPresenter与每个Canvas之间都会有MyControl。您需要在这些Canvas.Left上设置Canvas.TopContentPresenters属性。

你有一个循环,从AssociatedObject向上运行可视树,找到祖先Canvas。您可以使用以下内容修改此内容以查找画布的直接子项:

            _immediateChild = AssociatedObject;
            _parent = VisualTreeHelper.GetParent(AssociatedObject);
            while (_parent.GetType() != typeof(Canvas))
            {
                _immediateChild = _parent;
                _parent = VisualTreeHelper.GetParent(_parent);
            }