代码之家  ›  专栏  ›  技术社区  ›  Alex

c#/WPF产品配置器/可拖动项目

  •  -1
  • Alex  · 技术社区  · 7 年前

    我目前正在用C#/WPF构建产品配置程序。该产品类似于定制的出口条。它是由长度可变的铝型材制成的。您可以选择插座并沿铝型材放置。

    我们已经有了数据模型。我们有属性为“长度”的类“profile”,以及属性为“位置”、“类型”等的类“items”。

    我做了一个游戏来可视化数据。我有一个主画布,在那里我将轮廓绘制为矩形,并且使用属性“width”。属于该产品的项目位于列表中。我正在使用for循环为列表“items”中的每个插件插入一个wpf来绘制项目。

    当我更改数据时,我必须清除画布并重新绘制。我认为下一步将是将类的变量绑定到WPF属性,例如插头的位置或概要文件的长度。

    之后,应选择/拖动插头以更改其位置(例如,在5mm网格中)。这就是我被困的品脱。我知道我可以通过“OnLeftMouseButton”这样的操作来选择和拖动插头。现在的问题是:我应该把插头放在什么类型的容器中?

    我想我可以将插件的WPF代码封装在UserControl中。这是正确的方法吗?据我所知,我可以使用Hittest选择用户控件。Hittestresult将放入选定的列表中。为了显示选择,我可以使用UserControl的Borderthickness/Brush。对于拖动,我可以使用ManufiliationDelta更改位置(并更改绑定位置变量)。因为插件的数量是可变的,所以我必须从C#代码生成UserControls。 我知道使用用户控件进行Hittest并不容易,因为它们实际上并不“可见”。

    我对C有点陌生,我很难在互联网上找到有类似问题或项目的人,可能是因为我在搜索错误的单词。我的假设正确吗?您会为此使用哪些WPF控件?

    1 回复  |  直到 7 年前
        1
  •  1
  •   P.Manthe    7 年前

    我用过 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>
    

    这是背后的代码。一些基本模型视图:

    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参数来控制捕捉精度。