-1

I have a list of items, which every item include a few of notes, like this:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        List<Item> items = new List<Item>();
        Item item1 = new Item() { Title = "First Item" };
        Item item2 = new Item() { Title = "Second Item" };

        item1.ItemNotes.Add(new ItemNote() { Note = "first_note" });
        item1.ItemNotes.Add(new ItemNote() { Note = "second_note" });
        item1.ItemNotes.Add(new ItemNote() { Note = "third_note" });
        item2.ItemNotes.Add(new ItemNote() { Note = "fourth_note" });
        item2.ItemNotes.Add(new ItemNote() { Note = "fifth_note" });

        items.Add(item1);
        items.Add(item2);

        ic_tasks.ItemsSource = items;
    }
}

public class Item
{
    public Item()
    {
        this.ItemNotes = new ObservableCollection<ItemNote>();
    }
    public string Title { get; set; }
    public ObservableCollection<ItemNote> ItemNotes { get; set; }
}
public class ItemNote
{
    public string Note { get; set; }
}

In XAML I present those items by ItemsControl, like this:

<Grid>
   <ItemsControl Name="ic_tasks">
      <ItemsControl.ItemTemplate>
          <DataTemplate DataType="{x:Type local:Item}">
              <StackPanel Orientation="Vertical">
                  <Border BorderThickness="1" CornerRadius="8" Background="DarkGray">
                      <StackPanel Orientation="Horizontal" Height="30">
                          <TextBox Text="{Binding Title}" Margin="5,5,5,5"/>
                          <Button Margin="5,5,5,5">Fold</Button>
                      </StackPanel>
                  </Border>
                  <ItemsControl ItemsSource="{Binding ItemNotes}">
                      <ItemsControl.ItemTemplate>
                          <DataTemplate DataType="{x:Type local:ItemNote}">
                              <TextBox Margin="40,5,5,5" Text="{Binding Note}"/>
                          </DataTemplate>
                      </ItemsControl.ItemTemplate>
                  </ItemsControl>
              </StackPanel>
          </DataTemplate>
      </ItemsControl.ItemTemplate>
   </ItemsControl>
</Grid>

And now my goal is to make those Items moveable. For example, I would like to be able to move the second item over the first item, like below:

Moving Item

What I tried? I try to wrap all ItemsControl by Canvas and bind position by Canvas.Top & Canvas.Left by using Mouse Events, but there's no such property for StackPanel which I want to move. There's only such propery for ItemsControl, like below:

<Canvas x:Name="canvas_of_items">
    <ItemsControl Name="ic_tasks" Canvas.Top="{Binding YPosition}" Canvas.Left="{Binding XPosition}">
        <...>
             <StackPanel Orientation="Horizontal" Height="30" PreviewMouseDown="StackPanel_MouseDown" PreviewMouseMove="StackPanel_MouseMove" PreviewMouseUp="StackPanel_MouseUp">
        <...>
    </ItemsControl>
</Canvas>

So my question is: What are the options to allow Items to be moved between themselves? Importantly, when moving the Item, it should be visible, not the mouse cursor itself.

1 Answers1

1

You can set the ItemsControl to place your items in a canvas using ItemsControl.ItemsPanel like this:

<ItemsControl Name="ic_tasks">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas></Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

But to move the items you cant just set the Canvas properties on the StackPanel because they are surrounded by ContentPresenter. Instead you use ItemsControl.ItemContainerStyle to set a style on these ContentPresentors and there you can do something like this:

<Style>
     <Setter Property="Canvas.Left" value="<<somthing - propebly a binding so it will be easy to change>>"
</Style>
Efraim Newman
  • 927
  • 6
  • 21