Reputation: 3582
I have an ItemsControl
with an ItemSource of Entities
which is an ObservableCollection<Entity>
.
The Entity
class contains a string Name
and int X,Y
properties with public {get;set;}
<ItemsControl x:Name="myCanvas" Grid.Row="1" ItemsSource="{Binding Path=Entities}" MouseMove="myCanvas_MouseMove" MouseDoubleClick="myCanvas_MouseDoubleClick" MouseUp="myCanvas_MouseUp" MouseDown="myCanvas_MouseDown" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=Y,Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=X,Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Rectangle Width="50" Height="50" RadiusX="4" RadiusY="4" Stroke="Black" Fill="Red" />
<Label Content="{Binding Path=Name}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When I add new Entity
in my collection I can see the change in the UI normally. I want to move by mouse those rectangles, that is why I capture the mouse position in the release event of the ItemsControl
and change the Entity
positions in my collection Entities
but I cannot see any changes in the UI.
MouseUp event
private void myCanvas_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Point point = Mouse.GetPosition(sender as FrameworkElement);
if (e.LeftButton == MouseButtonState.Released)
{
Entities[tempIndex].X = (int)point.X;
Entities[tempIndex].Y = (int)point.Y;
}
var binding = new Binding { Source = Entities };
myCanvas.SetBinding(ItemsControl.ItemsSourceProperty, binding);
}
tempIndex
is the Entity
that I want to move.
Upvotes: 0
Views: 256
Reputation: 4322
Your Canvas.Left is binding to Y (should be X).
Your Canvas.Top is binding to X (should be Y).
And Clemens is correct. Setting the binding for ItemsSource, in code, is not needed.
Here is some code that moves Entity #2 to the location you click on on myCanvas. I didn't implement the whole drag/drop, just moves the entity to where you click. I added a datagrid to the top to show the values of the Entities.
MainWindow.xaml
<Window x:Class="WpfApp11.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp11"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding Path=Entities}" AutoGenerateColumns="True" CanUserAddRows="False" />
<ItemsControl x:Name="myCanvas" Grid.Row="1" ItemsSource="{Binding Path=Entities}" MouseMove="myCanvas_MouseMove" MouseDoubleClick="myCanvas_MouseDoubleClick" MouseUp="myCanvas_MouseUp" MouseDown="myCanvas_MouseDown" Background="Beige" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X,Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y,Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Rectangle Width="50" Height="50" RadiusX="4" RadiusY="4" Stroke="Black" Fill="Red" />
<Label Content="{Binding Path=Name}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace WpfApp11
{
public partial class MainWindow : Window
{
public ObservableCollection<Entity> Entities { get; set; }
private int tempIndex = 1; // Always move box "2"
public MainWindow()
{
InitializeComponent();
DataContext = this;
Entities = new ObservableCollection<Entity>()
{
new Entity() { Name = "1", X=50, Y=50 },
new Entity() { Name = "2", X=150, Y=50 },
new Entity() { Name = "3", X=50, Y=150 },
new Entity() { Name = "4", X=150, Y=150 },
};
}
private void myCanvas_MouseMove(object sender, MouseEventArgs e)
{
}
private void myCanvas_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
}
private void myCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
}
private void myCanvas_MouseUp(object sender, MouseButtonEventArgs e)
{
Point point = Mouse.GetPosition(sender as FrameworkElement);
if (e.LeftButton == MouseButtonState.Released)
{
Entities[tempIndex].X = (int)point.X;
Entities[tempIndex].Y = (int)point.Y;
}
}
}
public class Entity : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
{
if (Equals(field, value))
{
return false;
}
field = value;
this.OnPropertyChanged(name);
return true;
}
protected void OnPropertyChanged([CallerMemberName]string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
#endregion
#region Property string Name
private string _Name;
public string Name { get { return _Name; } set { SetProperty(ref _Name, value); } }
#endregion
#region Property int X
private int _X;
public int X { get { return _X; } set { SetProperty(ref _X, value); } }
#endregion
#region Property int Y
private int _Y;
public int Y { get { return _Y; } set { SetProperty(ref _Y, value); } }
#endregion
}
}
Upvotes: 1