Following my previous question, I now can drag an item in a canvas through a behavior.
The problem is that the item new coordinates calculations are done internally in the behavior, and I'm not sure how to send them to the item's ViewModel without writing anything in the view.
My MainViewModel has an Items
collection :
public BindableCollection<ItemViewModel> Items { get; set; }
The ItemViewModel looks like this :
[ImplementPropertyChanged]
public class ItemViewModel
{
private readonly IEventAggregator events;
private Random r = new Random();
public ItemViewModel(IEventAggregator events)
{
this.events = events;
this.events.Subscribe(this);
// default values
this.BackgroundColor = this.RandomColor();
this.Width = 100;
this.Height = 100;
this.X = 10;
this.Y = 10;
}
public Brush BackgroundColor { get; set; }
public string Content { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public double X { get; set; }
public double Y { get; set; }
/// <summary>
/// https://stackoverflow.com/a/11282427/6776
/// </summary>
private SolidColorBrush RandomColor()
{
var properties = typeof(Brushes).GetProperties();
var count = properties.Count();
var color = properties.Select(x => new { Property = x, Index = this.r.Next(count) })
.OrderBy(x => x.Index)
.First();
return (SolidColorBrush)color.Property.GetValue(color, null);
}
}
And my DragBehavior, for now, is just a copy/paste of this code snippet.
And finally, my MainView displays the items like this (I'm using Caliburn.Micro to bind the items through x:Name
) :
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Width" Value="{Binding Path=Width}" />
<Setter Property="Height" Value="{Binding Path=Height}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Path=BackgroundColor}"
behaviors:DragBehavior.Drag="True">
<!-- contents -->
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I was thinking of adding something along the lines of this :
<Border ...
behaviors:DragBehavior.OnDropped="{Binding Dropped}">
And in the ItemViewModel :
public void Dropped(Point newCoordinates) {
// change the X and Y of the viewmodel
}
But I have no idea where to start, or even what to call it. Action ? Trigger ? It doesn't seem to relate to what I'm looking for.
The Gong DragDropBehavior library has a system where the item implements an interface and the behavior runs the proper method, but I don't really understand how it works (it's the first time I work with behaviors).