将内容从一个网格子项拖放到另一个网格子项

时间:2015-09-23 09:02:00

标签: c# wpf button drag-and-drop grid

这是我的第一篇文章所以请善待:D。

我正在寻找一种方法让我的程序的用户通过拖放将一个按钮(作为背景图像,并且是Grid-Children的内容)移动到另一个Grid-Children。

My Buttons由程序本身基于for-iteration中的数据库创建:

foreach (PC_Infos item in allPcsOnThisFloor)
{
    if (item != null)
    {
        roomToCoordinates(allPcsOnThisFloor[i].Room,out column, out row);
        Button btn = new Button();
        btn.Name = Name+ "_Button";
        btn.Background = new ImageBrush(my icon here);
        btn.Click += btn_Click;
        btn.SetValue(Grid.ColumnProperty, column);
        btn.SetValue(Grid.RowProperty, row);
        My_Grid.Children.Add (btn);
        i++;
    }
    else 
        break;
}

PC_Infos只是一个持有属性的类:PC_Name,Room和MAC_adress。

我的网格:

<Grid x:Name="Grid_10" AllowDrop="True">
    <Grid.Background>
        <ImageBrush ImageSource="C:\Users\XXX\XXX\buildingPlan.png"/>
    </Grid.Background>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        [...]
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        [...]
        <RowDefinition />
    </Grid.RowDefinitions>
</Grid>

现在有一种方法可以使用btn.*在绘制时获取当前位置(行和列),另一个btn.*在Grid-Child中创建此按钮的新副本当鼠标按下按钮时,鼠标当前是否已经结束? 或者甚至有办法将按钮从一个孩子“移动”到另一个孩子?

顺便说一句:我的程序应该显示一个建筑计划,其上有PC作为图标(按钮),在它们实际的位置。通过读取我的数据库中的“房间”列,源代码会进行粗略的猜测。但是房间不仅仅是一个地方。有人在门口的窗口工作,这应该由用户标记(拖放) 我在VS'13中使用了带有C#和.Net 4.5.1的WPF-Application。

PS:如果有人说:为什么网格和为什么地狱按钮? :D:当用户点击图标时,将显示具有系统值的新窗口,例如OS,RAM,CPU ....但我愿意接受任何实施。我现在还没有完成编程,所以我可能不知道最好的方法。

While I'm not allowed to post images with 0 Rep, here is a Link to an img wich shows my Grid over my buildingplan

希望你得到我的问题:D 谢谢你的帮助。如果有任何问题请问;)

1 个答案:

答案 0 :(得分:0)

我可能会误解你的问题,但据我所见,这里没有任何拖延:你想在UIElements周围移动Panel

首先,我建议使用Canvas来显示您的商品,而不是Grid,因为它会提供更大的灵活性。

假设您将此课作为主要对象:

public class PC_Infos
{
    public string PC_Name;
    public string Room;
    public string MAC_Adress;
}

我不喜欢在代码隐藏中构建控件,而是喜欢一个简单的包装器,如:

public class DragablePC : INotifyPropertyChanged
{
    public DragablePC(PC_Infos pc, double x = 0d, double y = 0d)
    {
        _pcItem = pc;
        PcRow = y;
        PcColumn = x;
    }

    private double _x;
    public double PcColumn
    {
        get { return _x; }
        set
        {
            if (value == _x) return;
            _x = value;
            RaisePropertyChanged("PcColumn");
        }
    }

    private double _y;
    public double PcRow
    {
        get { return _y; }
        set
        {
            if (value == _y) return;
            _y = value;
            RaisePropertyChanged("PcRow");
        }
    }

    PC_Infos _pcItem;

    public DragablePC(PC_Infos pc, double x = 0d, double y = 0d)
    {
        _pcItem = pc;
        PcRow = y;
        PcColumn = x;
    }

    public override string ToString() { return _pcItem.PC_Name; }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

此包装器只存储X / Y坐标和您的项目。它允许定义绑定源,如下所示:

AllPCS = allPcsOnThisFloor.Select(p => new DragablePC(p));

现在,您可以使用ItemsControl来显示您的商品。如上所述,我将Canvas用于ItemsPanel,并定义一个简单的ItemContainerStyle将其放置在其上。

    <ItemsControl Name="DDPanel" ItemsSource="{Binding Path=AllPCS}"
                  MouseMove="DDPanel_MouseMove">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" Background="LightGray"/>                    
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Path=PcRow}"/>
                <Setter Property="Canvas.Left" Value="{Binding Path=PcColumn}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type dnd:DragablePC}">
                <Border BorderBrush="Red" BorderThickness="2" CornerRadius="6" Padding="6, 12"
                        Background="White" MinWidth="70" 
                        MouseLeftButtonDown="Border_MouseLeftButtonDown"
                        MouseLeftButtonUp="Border_MouseLeftButtonUp">
                    <TextBlock Text="{Binding}" HorizontalAlignment="Center"/>
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

必须更新ItemTemplate以满足您的需求,最重要的部分是处理鼠标事件。

以下是我添加的处理程序:

    DragablePC _selected = null;
    Point cursorPos = new Point();

    private void DDPanel_MouseMove(object sender, MouseEventArgs e)
    {
        if (null == _selected) return;

        Point newPosition = e.GetPosition(DDPanel);
        _selected.PcColumn += newPosition.X - cursorPos.X;
        _selected.PcRow += newPosition.Y - cursorPos.Y;
        cursorPos = newPosition;
    }

    private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var uiItem = sender as FrameworkElement;
        var dpc = uiItem.DataContext as DragablePC;

        if (dpc == null) return;

        cursorPos = e.GetPosition(DDPanel);
        _selected = dpc;
    }

    private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        var uiItem = sender as FrameworkElement;
        var dpc = uiItem.DataContext as DragablePC;

        if (dpc == null) return;

        _selected = null;
    }

现在需要进行大量的调整,例如处理MouseLeave事件,为定位添加一些逻辑......但是现在你可以移动你的电脑。

希望这有帮助。