我有一个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>
答案 0 :(得分:1)
当您使用ItemsControl
时,生成的每个项目都会包含在ContentPresenter
中。可视化树看起来有点像:
System.Windows.Controls.ItemsControl System.Windows.Controls.ItemsPresenter System.Windows.Controls.Canvas System.Windows.Controls.ContentPresenter DragControlBehaviorTest.MyControl ...
(DragControlBehaviorTest
是我为试用你的代码而创建的项目的名称。)
Canvas.Left
和Canvas.Top
附加属性仅适用于Canvas
的直接子项。如果您将MyControl
直接放在Canvas
中,则MyControl
是Canvas
的孩子,因此设置Canvas.Left
和Canvas.Top
它会起作用。但是,如果您使用ItemsControl
生成MyControl
s,ContentPresenter
与每个Canvas
之间都会有MyControl
。您需要在这些Canvas.Left
上设置Canvas.Top
和ContentPresenters
属性。
你有一个循环,从AssociatedObject
向上运行可视树,找到祖先Canvas
。您可以使用以下内容修改此内容以查找画布的直接子项:
_immediateChild = AssociatedObject;
_parent = VisualTreeHelper.GetParent(AssociatedObject);
while (_parent.GetType() != typeof(Canvas))
{
_immediateChild = _parent;
_parent = VisualTreeHelper.GetParent(_parent);
}