我试图执行拖放方法来创建图表中的关系,直接与图表工具SQL Server Management Studio一致。例如,在下图中,用户将从User
实体拖动CustomerID
到Customer
实体,并在两者之间创建外键关系。在WPF中拖放的绘制图圆弧
关键的预期功能是当用户按照鼠标执行拖动操作时,绘制临时弧路径。移动的实体或关系一旦创建不是我遇到的问题。
对应于实体上图上的一些参考XAML:
<!-- Entity diagram control -->
<Grid MinWidth="10" MinHeight="10" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" IsHitTestVisible="False" Background="{StaticResource ControlDarkBackgroundBrush}">
<Label Grid.Row="0" Grid.Column="0" Style="{DynamicResource LabelDiagram}" Content="{Binding DiagramHeader, Mode=OneWay}" />
</Grid>
<ScrollViewer Grid.Row="1" Grid.Column="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Background="{StaticResource ControlBackgroundBrush}" >
<StackPanel VerticalAlignment="Top">
<uent:EntityDataPropertiesDiagramControl DataContext="{Binding EntityDataPropertiesFolder}" />
<uent:CollectionEntityPropertiesDiagramControl DataContext="{Binding CollectionEntityPropertiesFolder}" />
<uent:DerivedEntityDataPropertiesDiagramControl DataContext="{Binding DerivedEntityDataPropertiesFolder}" />
<uent:ReferenceEntityPropertiesDiagramControl DataContext="{Binding ReferenceEntityPropertiesFolder}" />
<uent:MethodsDiagramControl DataContext="{Binding MethodsFolder}" />
</StackPanel>
</ScrollViewer>
<Grid Grid.RowSpan="2" Margin="-10">
<lib:Connector x:Name="LeftConnector" Orientation="Left" VerticalAlignment="Center" HorizontalAlignment="Left" Visibility="Collapsed"/>
<lib:Connector x:Name="TopConnector" Orientation="Top" VerticalAlignment="Top" HorizontalAlignment="Center" Visibility="Collapsed"/>
<lib:Connector x:Name="RightConnector" Orientation="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Visibility="Collapsed"/>
<lib:Connector x:Name="BottomConnector" Orientation="Bottom" VerticalAlignment="Bottom" HorizontalAlignment="Center" Visibility="Collapsed"/>
</Grid>
</Grid>
我的当前的方法来这样做是为了:
1)启动在子拖动操作控制实体,如:
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
{
dragStartPoint = null;
}
else if (dragStartPoint.HasValue)
{
Point? currentPosition = new Point?(e.GetPosition(this));
if (currentPosition.HasValue && (Math.Abs(currentPosition.Value.X - dragStartPoint.Value.X) > 10 || Math.Abs(currentPosition.Value.Y - dragStartPoint.Value.Y) > 10))
{
DragDrop.DoDragDrop(this, DataContext, DragDropEffects.Link);
e.Handled = true;
}
}
}
2)创建的连接器装饰器时的拖动操作离开实体,诸如:
protected override void OnDragLeave(DragEventArgs e)
{
base.OnDragLeave(e);
if (ParentCanvas != null)
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(ParentCanvas);
if (adornerLayer != null)
{
ConnectorAdorner adorner = new ConnectorAdorner(ParentCanvas, BestConnector);
if (adorner != null)
{
adornerLayer.Add(adorner);
e.Handled = true;
}
}
}
}
3)画出弧形路径作为鼠标在连接器装饰器被移动,如:
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (!IsMouseCaptured) CaptureMouse();
HitTesting(e.GetPosition(this));
pathGeometry = GetPathGeometry(e.GetPosition(this));
InvalidateVisual();
}
else
{
if (IsMouseCaptured) ReleaseMouseCapture();
}
}
图Canvas
被绑定到视图模型,并且Canvas
上的实体和关系又被绑定到相应的视图模型。与整体框图一些XAML:
<ItemsControl ItemsSource="{Binding Items, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<lib:DesignerCanvas VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
<Setter Property="Canvas.Width" Value="{Binding Width}"/>
<Setter Property="Canvas.Height" Value="{Binding Height}"/>
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
和DataTemplate
S为的entites和关系:
<!-- diagram relationship -->
<DataTemplate DataType="{x:Type dvm:DiagramRelationshipViewModel}">
<lib:Connection />
</DataTemplate>
<!-- diagram entity -->
<DataTemplate DataType="{x:Type dvm:DiagramEntityViewModel}">
<lib:DesignerItem>
<lib:EntityDiagramControl />
</lib:DesignerItem>
</DataTemplate>
问题:的问题是,一旦开始拖动操作,鼠标移动不再跟踪并且连接器装饰者无法像在其他环境中那样绘制弧线。如果我释放鼠标并再次单击,则该弧开始绘制,但之后我失去了源对象。我试图想出一个方法来将鼠标移动与源对象结合在一起。
赏金:回到这个问题,我目前打算不用直接拖放来做到这一点。我目前计划为图控件添加一个DragItem和IsDragging DependencyProperty
,该控件可以保存正在拖动的项目,并标记是否发生拖动操作。然后,我可以使用DataTrigger
s更改基于IsDragging的Cursor
和Adorner
可见性,并且可以使用DragItem进行放置操作。
(但是,我期待奖项的另一个有趣的方法赏金请评论,如果需要更多的信息或代码来澄清这个问题。)
编辑:较低的优先级,但是我仍然在寻找更好的解决方案来实现拖放图表方法。希望在开源Mo+ Solution Builder中实施更好的方法。
谢谢亚当。我确实使用了Thumb控件来移动实体和关系,并在渲染后调整实体的大小。在这种情况下,我不认为我可以使用大拇指,因为在拖动过程中正在绘制弧路径,然后将其作为控件放置。除非你知道一个窍门! – 2011-06-16 04:22:05