与ItemsControl不同的MouseMove行为?

时间:2018-11-24 10:07:31

标签: c# wpf

我有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();调用它。

任何人都知道为什么会发生这种情况,或更确切地说,我在做什么错了?

2 个答案:

答案 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

这是在文本框和内容中添加模板,而不是完全按照您的意图进行操作。