2015-09-23 2 views
0

это мое первое сообщение, поэтому, пожалуйста, будьте добры: D.Перетаскивание содержимого из одной сетки-ребенка в другую

Я ищу способ, позволяющий пользователю моей программы перемещать кнопку (как изображение как backgroung, а также содержимое Grid-Children) другим Grid-Children путем перетаскивания ,

Мои кнопки создаются самой программой, основанной на базе данных в обмен на итерации:

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_Infos просто класс держит Свойства: PC_Name, номер и MAC_adress ничего.

Моя Сетка:

<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.* Wich выбирает текущий постион (строка и столбец), когда потащил, а другой btn.* которым создает новую копию этой кнопки в сетке -Чтобы мышь в данный момент закончилась, когда мышь нажала кнопку? Или есть даже способ «переместить» кнопку от одного ребенка к другому?

BTW: Моя программа должна показывать план здания с ПК как значки (кнопки) на нем в том месте, где они актуальны. Грубое предположение берет исходный код, читая столбец «Комната» в моем db. Но комната - это не просто одно место. Кто-то работает в окне еще один у двери, это должно быть отмечено пользователем (с перетаскиванием & drop) Я использую WPF-приложение в VS'13 с C# и .Net 4.5.1.

PS: Если есть кто-нибудь, кто говорит: «Почему сетка и почему адские кнопки? : D: Когда пользователь нажимает на значок, появится новое окно с системным значением, например OS, RAM, CPU .... Но я открыт для любой реализации. Я так долго не программировал, поэтому я, возможно, не знаю, как это сделать.

While I'm not allowed to post images with 0 Rep, here is a Link to an img wich shows my Grid over my buildingplan

Надеется, что вы получите мой вопрос: D Спасибо за вашу помощь. Если у вас возникли вопросы, обращайтесь;)

ответ

0

Я могу неправильно понять вашу проблему, но, насколько я вижу, там нет drag'n'drop: вы хотите переместить UIElements вокруг вашего Panel.

Во-первых, я бы рекомендовал использовать Canvas для отображения ваших товаров, а не Grid, поскольку он будет предлагать гораздо большую гибкость.

Допустим, у вас есть этот класс в качестве основного объекта:

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 для отображения элементов. Как указано выше, я буду использовать Canvas для ItemsPanel и определить простой 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> 

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

Вот обработчики я добавил:

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

Теперь это требует много настройки, таких как обработка MouseLeave события, добавив некоторую логику в отношении расположения ... но теперь вы можете переместить ваш компьютер все вокруг.

Надеюсь, это поможет.

+0

Спасибо за второй абзац: D Теперь я использую холст, который (как вы уже отметили) гораздо более гибкий и простой, а вместо кнопок я использую теперь прямоугольники. С помощью «MyCanvas_MouseDown», «MyCanvas_MouseMove» и «MyCanvas_MouseMove» ActionHandlers и глобальной переменной _DragInProgress_ я могу обрабатывать Movements. Когда вызывается «MouseDown», код получает прямоугольник подслоя и перерисовывает его во время «MouseMove» с помощью deltaX и deltaY мыши, так как нажатие любой кнопки мыши вниз. –

+0

Извините за то, что вы не использовали свой код или так, как вы бы это сделали, но посмотрите на PS моего кискана. Я редко отношусь к программированию, и, честно говоря, я даже не понимаю каждый бит вашего кода. Но ты дал мне новое направление. –

+0

Рад, что это могло бы помочь. Если вы работаете в WPF, вам определенно следует следить за привязкой и шаблонами. – xum59

Смежные вопросы