Silverlight 4: почему предметы нельзя передвигать? - PullRequest
1 голос
/ 24 августа 2010

Есть «поле», в котором можно перетаскивать некоторые элементы:

Вот код XAML:

                <Canvas Height="180" Width="169" >
                    <Image Canvas.Left="0" Canvas.Top="0" Height="180" Width="149"
                           Source="../Picts/field.png"  />

                    <Pages:FieldItem x:Name="Item2" Canvas.Left="129" Canvas.Top="34"
                                MouseLeftButtonDown="Item1_OnMouseLeftButtonDown"
                                MouseLeftButtonUp="Item1_MouseLeftButtonUp"
                                MouseMove="Item1_MouseMove"
                                />
                </Canvas>

И код позади:

    private bool bIsCaptured = false;
    double mouseVerticalPosition;
    double mouseHorizontalPosition;

    private void Item1_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        ((FrameworkElement)sender).CaptureMouse();
        bIsCaptured = true;
        mouseVerticalPosition = e.GetPosition(null).Y;
        mouseHorizontalPosition = e.GetPosition(null).X;
    }

    private void Item1_MouseMove(object sender, MouseEventArgs e)
    {
        if (bIsCaptured)
        {
            UserControl item = sender as UserControl;
            if (item != null)
            {
                // Calculate the current position of the object.
                double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
                double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
                double newTop = deltaV + (double)item.GetValue(Canvas.TopProperty);
                double newLeft = deltaH + (double)item.GetValue(Canvas.LeftProperty);

                // Set new position of object.
                item.SetValue(Canvas.TopProperty, newTop);
                item.SetValue(Canvas.LeftProperty, newLeft);

                // Update position global variables.
                mouseVerticalPosition = e.GetPosition(null).Y;
                mouseHorizontalPosition = e.GetPosition(null).X;
            }
        }
    }

    private void Item1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        UserControl item = sender as UserControl;
        bIsCaptured = false;
        if (item != null)
        {
            item.ReleaseMouseCapture();
        }
    }

Моя задача - отобразить коллекцию предметов, которые связаны со списком объектов.Как это сделать, описано в теме: Silverlight 4: как отобразить список пользовательских элементов управления (не в порядке списка) .

Единственный недостаток предлагаемого подхода: элементы больше не перетаскиваются ...

Здесь, если обновить код XAML элементов управления "держатель" (предоставляется для целей согласованности):

<Canvas Height="180" Width="169" Background="Beige" HorizontalAlignment="Center" >
             <Image Canvas.Left="0" Canvas.Top="0" Height="180" Width="149"
                   Source="../Picts/field.png"  />
             <Pages:MyItemsControl ItemsSource="{Binding SquadFieldPlayers}">
                <Pages:MyItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                         <Canvas Height="180" Width="169" Background="Transparent"
                                 HorizontalAlignment="Center" />
                    </ItemsPanelTemplate>
                </Pages:MyItemsControl.ItemsPanel>
                <Pages:MyItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Pages:FieldItem 
                             MouseLeftButtonDown="Item1_OnMouseLeftButtonDown" 
                             MouseLeftButtonUp="Item1_MouseLeftButtonUp"
                             MouseMove="Item1_MouseMove"
                             />
                    </DataTemplate>
                 </Pages:MyItemsControl.ItemTemplate>
             </Pages:MyItemsControl >
         </Canvas>

Вызываются все обработчики событий мыши, но элементы не являются действительно подвижными ... почему?

1 Ответ

1 голос
/ 27 августа 2010

Все еще не уверен, как это должно работать, но я нашел обходной путь.Метод Item1_MouseMove был обновлен для выполнения следующих операций:

  1. Найти объект данных, к которому привязан элемент управления;
  2. Установить свойства FieldCoordX и FieldCoordY этого объекта вместо установки'Canvas.LeftProperty' и 'Canvas.RightProperty' элемента управления.

Это выглядит следующим образом:

    private void Item1_MouseMove(object sender, MouseEventArgs e)
    {
        if (bIsCaptured)
        {
            FrameworkElement element = sender as FrameworkElement;
            if (element != null)
            {
                ISquadPlayerViewModel vmPlayer = element.DataContext as ISquadPlayerViewModel;
                if (vmPlayer != null)
                {
                    // Calculate the current position of the object.
                    double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
                    double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
                    double newLeft = deltaH + vmPlayer.FieldCoordX;
                    double newTop = deltaV + vmPlayer.FieldCoordY;

                    // Set new position of object.
                    vmPlayer.FieldCoordX = newLeft;
                    vmPlayer.FieldCoordY = newTop;
                }

                // Update position global variables.
                mouseVerticalPosition = e.GetPosition(null).Y;
                mouseHorizontalPosition = e.GetPosition(null).X;
            }
        }
    }

Еще один элемент, который будет добавлен в исходное описание, настройкаобъект ItemsControl, который содержит все элементы управления:

public class MyItemsControl : ItemsControl
{
    protected override void PrepareContainerForItemOverride(
                                  DependencyObject element, object item)
    {
        FrameworkElement contentitem = element as FrameworkElement;
        if (contentitem != null)
        {
            Binding leftBinding = new Binding("FieldCoordX");
            Binding topBinding = new Binding("FieldCoordY");
            leftBinding.Mode = BindingMode.TwoWay;
            topBinding.Mode = BindingMode.TwoWay;
            contentitem.SetBinding(Canvas.LeftProperty, leftBinding);
            contentitem.SetBinding(Canvas.TopProperty, topBinding);

            base.PrepareContainerForItemOverride(element, item);
        }
    }
}

Как вы можете видеть, наши элементы управления уже связаны со свойствами объектов данных.Поэтому нам нужно обновить не контрольные данные, а данные объекта.

Если кому-то интересно узнать больше, спросите.Я постараюсь помочь.

...