我目前正在C#/ WPF中构建产品配置程序。该产品类似于定制插座条。它由可变长度的铝型材制成。您可以选择出口并将它们放在铝型材上。
我们已经有了数据模型。我们有班级"简介"具有"长度"等属性和班级"项目"使用" position"," type"等
我做了一个可视化数据的功能。我有一个MainCanvas,其中我将配置文件绘制为矩形,并且我使用属性" width"。属于该产品的项目位于列表中。我使用for循环绘制项目,为列表中的每个插件插入一个wpf" items"。
当我更改数据时,我必须清除画布并重绘。我认为下一步是将类的变量绑定到WPF属性,例如插件的位置或配置文件的长度。
稍后,应选择/拖动插头以更改其位置(例如,在5毫米的网格中)。那是我陷入困境的品脱。我知道我可以选择和拖动插头,例如" OnLeftMouseButton"。现在的问题是:我应该在什么类型的容器中插入插头?
我以为我可以将一个插件的WPF-Code包装在UserControl中。这是正确的方法吗?据我所知,我可以使用Hittest选择UserControl。 Hittestresult将被列入选中的列表。为了显示选择,我可以使用UserControl的Borderthickness / Brush。对于拖动,我可以使用ManupilationDelta更改位置(并更改绑定的位置变量)。因为插件的数量是可变的,所以我必须从C#-Code生成UserControls。 我知道Hittest使用UserControls并不容易实现,因为它们并非真正可见"。
我是C#的新手,我很难在互联网上找到有类似问题或项目的人,也许是因为我在搜索错误的单词。我的假设是否正确?您将使用什么WPF控制?
答案 0 :(得分:1)
我使用了this answer并添加了一些修改。
我使用ItemControl
创建包含不同对象的视图。这样,您只需将对象添加到列表中即可添加图像。容器是Canvas
,但它可以是任何内容,因为该位置由RenderTransform
控制:
<ItemsControl Name="MainView" ItemsSource="{Binding ListObjects}">
<ItemsControl.ItemsPanel >
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:MVDragableObject}">
<local:DragableObject/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
这是背后的代码。一些基本的ModelView:
public class MVObjectManager
{
public ObservableCollection<MVDragableObject> ListObjects { get; set; }
public MVObjectManager()
{
ListObjects = new ObservableCollection<MVDragableObject>();
}
}
public class MVDragableObject
{
}
填充和绑定容器的代码。您可以注意到我在集合中添加了3个项目:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MVObjectManager Manager=new MVObjectManager();
Manager.ListObjects.Add(new MVDragableObject());
Manager.ListObjects.Add(new MVDragableObject());
Manager.ListObjects.Add(new MVDragableObject());
MainView.DataContext = Manager;
}
}
我定义了一个非常简单的UserControl
。您可以自定义它:
<UserControl x:Class="StackFill.DragableObject"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid>
<Rectangle Fill="Red" Height="30" Width="30"/>
</Grid>
</UserControl>
以下是管理拖放行为的代码:
public partial class DragableObject : UserControl
{
public DragableObject()
{
InitializeComponent();
this.MouseLeftButtonDown += new MouseButtonEventHandler(DragableObject_MouseLeftButtonDown);
this.MouseLeftButtonUp += new MouseButtonEventHandler(DragableObject_MouseLeftButtonUp);
this.MouseMove += new MouseEventHandler(DragableObject_MouseMove);
}
protected bool isDragging;
private Point clickPosition;
private void DragableObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
var draggableControl = sender as UserControl;
clickPosition = e.GetPosition(this.Parent as UIElement);
draggableControl.CaptureMouse();
}
private void DragableObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isDragging = false;
var draggable = sender as UserControl;
draggable.ReleaseMouseCapture();
}
private void DragableObject_MouseMove(object sender, MouseEventArgs e)
{
var draggableControl = sender as UserControl;
if (isDragging && draggableControl != null)
{
Point currentPosition = e.GetPosition(this.Parent as UIElement);
var transform = draggableControl.RenderTransform as TranslateTransform;
if (transform == null)
{
transform = new TranslateTransform();
draggableControl.RenderTransform = transform;
}
transform.X = snapPosition(currentPosition.X - clickPosition.X, 10);
transform.Y = snapPosition(currentPosition.Y - clickPosition.Y, 10);
}
}
private double snapPosition(double position, double gridSize)
{
return (Math.Truncate(position / gridSize) * gridSize);
}
}
您可以通过更改gridSize参数来控制捕捉精度。