我有WPF表单,在XAML中,我有一个标签,在按住MouseDown时,我可以在表单上移动,而在MouseRelease上,它可以保持在新位置。 一切正常。
XAML代码:
<Canvas>
<Label Content="Label"
Background="ForestGreen"
Padding="12,7"
Canvas.Left="{Binding XPosition}"
Canvas.Top="{Binding YPosition}"
MouseDown="Label_MouseDown"
MouseUp="Label_MouseUp"
MouseMove="Label_MouseMove"/>
</Canvas>
C#
public partial class frmTables : Window, INotifyPropertyChanged
{
private Point BasePoint = new Point(0.0, 0.0);
private double DeltaX = 0.0;
private double DeltaY = 0.0;
private bool moving = false;
private Point PositionInLabel;
public frmTables()
{
InitializeComponent();
this.DataContext = this;
}
public double XPosition
{
get { return BasePoint.X + DeltaX; }
}
public double YPosition
{
get { return BasePoint.Y + DeltaY; }
}
private void Label_MouseDown(object sender, MouseButtonEventArgs e)
{
Label l = e.Source as Label;
if (l != null)
{
l.CaptureMouse();
moving = true;
PositionInLabel = e.GetPosition(l);
lblCoord.Content = "MouseDown";
}
}
private void Label_MouseMove(object sender, MouseEventArgs e)
{
if (moving)
{
Point p = e.GetPosition(null);
DeltaX = p.X - BasePoint.X - PositionInLabel.X;
DeltaY = p.Y - BasePoint.Y - PositionInLabel.Y;
RaisePropertyChanged("XPosition");
RaisePropertyChanged("YPosition");
lblCoord.Content = DeltaX + ":" + DeltaY;
}
}
private void Label_MouseUp(object sender, MouseButtonEventArgs e)
{
Label l = e.Source as Label;
if (l != null)
{
l.ReleaseMouseCapture();
BasePoint.X += DeltaX;
BasePoint.Y += DeltaY;
DeltaX = 0.0;
DeltaY = 0.0;
moving = false;
lblCoord.Content = BasePoint.X + ":" + BasePoint.Y;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
一切正常,直到我更改XAML,并在运行时从后面的代码创建两个标签:
<Canvas>
<ItemsControl Name="btnTableImageList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="Label"
Background="ForestGreen"
Padding="12,7"
Canvas.Left="{Binding XPosition}"
Canvas.Top="{Binding YPosition}"
MouseDown="Label_MouseDown"
MouseUp="Label_MouseUp"
MouseMove="Label_MouseMove"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
除从后面的代码生成XLab和更改XAML之外,其他所有内容均保持不变。现在,如果我将MouseDown放在标签上并移动,那么MouseDown和MouseMove都不会起作用,因为我可以在lblCoord.Content
中看到测试消息。
如果需要,我可以向您展示标签生成代码,但这没什么特别的,只是一个带有for循环的类可以创建一定数量的标签,而我在WindowLoaded上用btnTableImageList.ItemsSource = tableLbl.CreateTableLabels();
调用它。
任何人都知道为什么会发生这种情况,或更确切地说,我在做什么错了?
答案 0 :(得分:0)
ItemsControl的标准ItemsPanel是StackPanel,因此更改Canvas.Left / Top时不会看到任何效果。您可以修改ItemsPanel来提供画布。
<Canvas>
<ItemsControl Name="btnTableImageList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="Label"
Background="ForestGreen"
Padding="12,7"
Canvas.Left="{Binding XPosition}"
Canvas.Top="{Binding YPosition}"
MouseDown="Label_MouseDown"
MouseUp="Label_MouseUp"
MouseMove="Label_MouseMove"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
注意:仍然缺少一些东西;有关完整的解决方案,请参见Setting Canvas properties in an ItemsControl DataTemplate
答案 1 :(得分:0)
我认为您要在此处进行的工作比第一步代码迈出了一大步。因为它涉及许多您可能没有看过的wpf概念。
Stackpanel只是您在这里需要了解的一部分。
我建议您下载并安装snoop。 当您运行它时,您会得到一个奇怪的工具栏,上面有一些瞄准镜对象。 在窗口上拖动一个,然后出现一个新窗口。 将鼠标悬停在标签之一所在的位置,然后同时按Shift + Ctrl。 您将看到控件树。 您的标签将位于contentpresenter内部,而该标签直接在画布中显示。这是您需要将canvas.top和canvas.left设置为打开的方式。
当您尝试操作该控件时,您会注意到在其中进行操作很麻烦。 为什么这么难? (您可能会认为)。 那是因为您打算使用绑定和模板而不是直接添加控件。 因此,将窗口的数据上下文设置为一个视图模型,然后将一个可观察的视图模型集合从那里绑定到itemscontrol的itemssource。然后,这些后面的视图模型中的每个视图模型都将暴露left和top属性,这些属性用于定位您的ui(标签)。
这里有一个工作样本说明了绑定和模板化的方法:
https://1drv.ms/u/s!AmPvL3r385QhgooJ94uO6PopIDs4lQ
这是在文本框和内容中添加模板,而不是完全按照您的意图进行操作。