【问题标题】:Drag and Drop content from one grid-child to another将内容从一个子网格拖放到另一个子网格
【发布时间】:2015-09-23 09:01:59
【问题描述】:

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

我的按钮是由程序本身基于数据库在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 应用程序。

PS:如果有人说:为什么是 Grid 以及为什么是地狱按钮? :D : 当用户点击图标时,会出现一个带有系统值的新窗口,例如 OS、RAM、CPU...。但我对任何实施持开放态度。好久没做编程了,可能不知道最好的方法。

While I'm not allowed to post images with 0 Rep, here is a Link to an img which shows my Grid over my buildingplan http://alexander.valerius.wilhelm-gym.net/Grid.PNG

【问题讨论】:

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


    【解决方案1】:

    我可能误解了你的问题,但据我所知,这里没有拖放:你想在你的Panel 周围移动UIElements

    首先,我建议使用 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 来显示您的项目。如上所述,我将为ItemsPanel 使用Canvas,并定义一个简单的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 事件、为定位添加一些逻辑……但您现在可以四处移动您的 PC。

    希望这会有所帮助。

    【讨论】:

    • 感谢第二段 :D 现在我使用的画布(正如你已经提到的)更灵活、更容易,而不是我现在使用的矩形按钮。使用MyCanvas_MouseDownMyCanvas_MouseMoveMyCanvas_MouseMove ActionHandlers 和一个全局变量DragInProgress,我可以处理运动。当MouseDown 被调用时,代码获取底层矩形并重新绘制它,而MouseMove 使用鼠标的deltaX 和deltaY,因为按下任何鼠标按钮。
    • 很抱歉没有使用您的代码或您应该使用的方式,但请查看我的 questinon 的 PS。我对编程比较陌生,老实说,我什至不理解你的每一点代码。但你给了我一个新的方向
    • 很高兴它可以提供帮助。如果您使用 WPF,则绝对应该关注绑定和模板。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多