Различное поведение MouseMove с ItemsControl? - PullRequest
0 голосов
/ 24 ноября 2018

У меня есть форма 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>

Все остальное остается прежним, за исключением создания этих лабораторий из кода позади и изменения XAML.Теперь, если я держу MouseDown на ярлыке и перемещаюсь, ничего не происходит, кроме MouseDown и MouseMove работают, так как я могу видеть тестовые сообщения в lblCoord.Content.

Если вам нужно, я могу показать вам код генерации метки, но это ничегоособый, просто класс с циклом for для создания определенного количества меток, и я вызываю его в WindowLoaded с помощью btnTableImageList.ItemsSource = tableLbl.CreateTableLabels();.

Кто-нибудь знает, почему это происходит, или, если быть более точным, что яЯ делаю не так?

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Я думаю, что вы пытаетесь сделать здесь, это большой шаг за пределы вашего первого куска кода.Поскольку он затрагивает ряд концепций wpf, которые вы, вероятно, еще не рассматривали.

Stackpanel - это только часть того, что вам необходимо здесь понять.

Я рекомендую вам скачать и установить Snoop.Когда вы запускаете его, вы получаете странную панель инструментов с некоторыми прицелами.Перетащите один поверх окна, и появится новое окно.Наведите указатель мыши на то место, где находится один из ваших ярлыков, и одновременно нажмите shift + ctrl.Вы увидите дерево элементов управления.Ваша метка будет находиться внутри Contentpresenter, и именно это идет прямо на холст.Именно для этого вам нужно установить canvas.top и canvas.left.

Вы заметите, когда попробуете манипулировать этим элементом управления, так как работа в нем была неприятной.Почему это так сложно?(вы, вероятно, подумаете).Это потому, что вы намереваетесь использовать привязку и шаблоны вместо непосредственного добавления элементов управления.Следовательно, установите текст данных окна в модель представления, свяжите наблюдаемую коллекцию моделей представления оттуда с источником элементов управления элементами.Каждая из этих последних моделей представления затем выставляет свойства left и top, которые используются для позиционирования вашего элемента пользовательского интерфейса (label).

Вот рабочий пример, иллюстрирующий подход связывания и шаблонирования:

https://1drv.ms/u/s!AmPvL3r385QhgooJ94uO6PopIDs4lQ

Это шаблонизируется в текстовые поля и прочее, а не делает именно то, что вы пытаетесь сделать.

0 голосов
/ 24 ноября 2018

Стандартной ItemsPanel ItemsControl является StackPanel, поэтому вы не увидите никакого эффекта при изменении Canvas.Left / Top.Вместо этого вы можете изменить ItemsPanel для предоставления Canvas.

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

ПРИМЕЧАНИЕ: все еще чего-то не хватает;полное решение см. в Настройка свойств Canvas в шаблоне данных ItemsControl

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...