As a beginner, I spent a ton of time creating a canvas that you can draw rectangles on -- and then selecting a rectangle so you can move it around or resize it.
So I am pretty happy with how this works. But now I need to add the second part to it. Every rectangle represents a section on the screen (the black canvas represents the user's screen). So when the user draws a rectangle, I want to automatically create a new instance of class Section in my ViewModel's ObservableCollection<Section>.
Section.cs looks like this:
public class Section { public int SectionId { get; set; } public int Width { get; set; } public int Height { get; set; } public int X { get; set; } public int Y { get; set; } public SectionType SectionType { get; set; } [ForeignKey("Layout")] public int LayoutId { get; set; } [ForeignKey("LayoutId")] public virtual Layout Layout { get; set; } }
My XAML looks like this:
<Canvas x:Name="LayoutCanvas" Grid.Row="2" Grid.ColumnSpan="2" Background="#FF2B2B2B" Loaded="Canvas_Loaded" MouseDown="Designer_MouseDown" MouseUp="Designer_MouseUp" MouseLeave="Designer_MouseLeave" MouseMove="Designer_MouseMove"/>
My Code-behind has all the mouse handlers:
private void Designer_MouseDown(object sender, MouseButtonEventArgs e) { if (e.Source != LayoutCanvas) { RemoveAdorners(e); } else { CreateNewSection(e); DeselectSection(); } } private void CreateNewSection(MouseButtonEventArgs e) { _startPoint = e.GetPosition(LayoutCanvas); _rect = new Rectangle { Fill = Brushes.Brown, Opacity = .8 }; Canvas.SetLeft(_rect, _startPoint.X); Canvas.SetTop(_rect, _startPoint.X); LayoutCanvas.Children.Add(_rect); }
private void Designer_MouseMove(object sender, MouseEventArgs e)
{
if (!_isDown)
{
DrawSection(e);
}
else
{
MoveSection(e);
}
}private void MoveSection(MouseEventArgs e)
{
if ((_isDragging == false) &&
((Math.Abs(e.GetPosition(LayoutCanvas).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(LayoutCanvas).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
_isDragging = true;
if (_isDragging)
{
Point position = Mouse.GetPosition(LayoutCanvas);
var newTop = position.Y - (_startPoint.Y - _originalTop);
var newBottom = newTop + selectedElement.RenderSize.Height;
var newLeft = position.X - (_startPoint.X - _originalLeft);
var newRight = newLeft + selectedElement.RenderSize.Width;
if (newTop >= 0 && newBottom <= LayoutCanvas.ActualHeight)
Canvas.SetTop(selectedElement, newTop);
if (newLeft >= 0 && newRight <= LayoutCanvas.ActualWidth)
Canvas.SetLeft(selectedElement, newLeft);
}
}
private void DrawSection(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Released || _rect == null)
return;
var pos = e.GetPosition(LayoutCanvas);
var x = Math.Min(pos.X, _startPoint.X);
var y = Math.Min(pos.Y, _startPoint.Y);
var w = Math.Max(pos.X, _startPoint.X) - x;
var h = Math.Max(pos.Y, _startPoint.Y) - y;
_rect.Width = w;
_rect.Height = h;
Canvas.SetLeft(_rect, x);
Canvas.SetTop(_rect, y);
}
How do I two-way bind this? I want the Section instance to:
- Automatically be created if a rectangle is created
- Automatically be updated if a rectangle changes in size or position
What I have read is that I need to use ItemsControl to make this happen; with ItemsSource set to my ObservableCollection<Section>. I have tried, but failed.