C# 将内容从一个网格子级拖放到另一个网格子级
我正在寻找一种方法,让我的程序的用户通过拖放将一个按钮(作为图像作为背景,是网格子项的内容)移动到另一个网格子项 “我的按钮”是由程序本身根据for迭代中的数据库创建的:C# 将内容从一个网格子级拖放到另一个网格子级,c#,wpf,button,drag-and-drop,grid,C#,Wpf,Button,Drag And Drop,Grid,我正在寻找一种方法,让我的程序的用户通过拖放将一个按钮(作为图像作为背景,是网格子项的内容)移动到另一个网格子项 “我的按钮”是由程序本身根据for迭代中的数据库创建的: foreach (PC_Infos item in allPcsOnThisFloor) { if (item != null) { roomToCoordinates(allPcsOnThisFloor[i].Room,out column, out row); Button
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\u Infos
只是一个包含属性的类:PC\u名称、房间和MAC\u地址,没有其他属性
我的网格:
<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.*
在鼠标放下按钮时在鼠标当前所在的子网格中创建此按钮的新副本?
或者甚至有没有办法将按钮从一个孩子“移动”到另一个孩子
顺便说一句:我的程序应该显示一个建筑平面图,上面的图标(按钮)是电脑实际所在的位置。通过阅读MyDB中的“Room”列,源代码可以粗略猜测。但房间不仅仅是一个地方。有人在窗口工作,另一人在门上工作,这应该由用户标记(使用拖放)
我在VS'13中使用了一个WPF应用程序和C#和.NET4.5.1
PS:如果有人说:为什么是网格,为什么是地狱按钮D:当用户点击图标时,会出现一个带有系统值的新窗口,如OS、RAM、CPU。。。会出现的。但我对任何实施都持开放态度。我已经很久没有做编程了,所以我可能不知道最好的方法
我可能误解了您的问题,但据我所知,这里没有拖放:您想在
面板周围移动ui元素
首先,我建议使用画布
来显示项目,而不是网格
,因为它将提供更大的灵活性
假设您将该类作为主要对象:
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>
这现在需要很多调整,例如处理MouseLeave
事件,为定位添加一些逻辑。。。但是你现在可以到处移动你的电脑了
希望这能有所帮助。谢谢第二段:D现在我使用的画布(正如你已经提到的)更灵活、更容易,而不是现在使用的按钮矩形。使用MyCanvas\u MouseDown
、MyCanvas\u MouseMove
和MyCanvas\u MouseMove
操作处理程序和全局变量DragInProgress,我可以处理移动。调用MouseDown
时,代码会获取参考底图矩形并重新绘制它,而MouseMove
自按下任何鼠标按钮后,使用鼠标的deltaX和deltaY进行重新绘制。很抱歉,没有使用您的代码或您本来可以使用的方式,但是看看我的questinon的PS。我对编程相对来说是新手,老实说,我甚至不理解你的每一段代码。但是你给了我一个新的方向很高兴它能帮上忙。如果您使用的是WPF,那么您肯定应该关注绑定和模板。
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;
}