我创建了一个简单的程序,使用MVVM Pattern将Rectangle绘制到canvas。然后我需要调整绘制的矩形的大小
我一直在寻找一个代码如何调整大小然后我找到了这个博客
https://denisvuyka.wordpress.com/2007/10/15/wpf-simple-adorner-usage-with-drag-and-resize-operations/
此博客分享了解决方案,因此我下载了它。
然后在我的代码中实现
这是我的xaml
<Grid>
<ItemsControl ItemsSource="{Binding RectItems, Source={x:Static local:Vm.instance}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="canvas" Background="Transparent" Height="{Binding ElementName=window}" Width="{Binding ElementName=window}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<ei:CallMethodAction MethodName="MouseDownEvent" TargetObject="{x:Static local:Vm.instance}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<ei:CallMethodAction MethodName="MouseMoveEvent" TargetObject="{x:Static local:Vm.instance}"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<ei:CallMethodAction MethodName="PreviewMouseLeftButtonDownEvent" TargetObject="{x:Static local:Vm.instance}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="Transparent" Stroke="Red" StrokeThickness="1"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
这是我的模特
public class RectItem : INotifyPropertyChanged
{
private double _x;
public double X
{
get { return _x; }
set
{
_x = value;
RaisePropertyChanged("X");
}
}
private double _y;
public double Y
{
get { return _y; }
set
{
_y = value;
RaisePropertyChanged("Y");
}
}
private double _width;
public double Width
{
get { return _width; }
set
{
_width = value;
RaisePropertyChanged("Width");
}
}
private double _height;
public double Height
{
get { return _height; }
set
{
_height = value;
RaisePropertyChanged("Height");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
这是我的ViewModel
AdornerLayer aLayer;
bool _isDown;
bool _isDragging;
bool selected = false;
UIElement selectedElement = null;
Point _startPoint;
private double _originalLeft;
private double _originalTop;
//end of variable declaration for resizing
public ObservableCollection<RectItem> RectItems { get; set; }
private Point startPoint;
public Vm()
{
RectItems = new ObservableCollection<RectItem>();
}
public void MouseDownEvent(object sender, MouseButtonEventArgs e)
{
startPoint = Mouse.GetPosition((IInputElement)sender);
}
public void MouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Released)
return;
if (selected) return;
var pos = Mouse.GetPosition((IInputElement)sender);
// Set the position of rectangle
var x = Math.Min(pos.X, startPoint.X);
var y = Math.Min(pos.Y, startPoint.Y);
// Set the dimenssion of the rectangle
var w = Math.Max(pos.X, startPoint.X) - x;
var h = Math.Max(pos.Y, startPoint.Y) - y;
if (RectItems.Count != 0)
{
var exist = RectItems.Where(xx => xx.X == x).LastOrDefault();
if (exist != null)
{
exist.Height = h;
exist.Width = w;
}
else
{
RectItems.Add(new RectItem
{
X = x,
Y = y,
Height = h,
Width = w
});
}
}
else
RectItems.Add(new RectItem
{
X = x,
Y = y,
Height = h,
Width = w
});
}
这是我调整大小的代码
public void PreviewMouseLeftButtonDownEvent(object sender, MouseButtonEventArgs e)
{
// Remove selection on clicking anywhere the window
if (selected)
{
selected = false;
if (selectedElement != null)
{
// Remove the adorner from the selected element
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = null;
}
}
// If any element except canvas is clicked,
// assign the selected element and add the adorner
if (e.Source != sender as Canvas)
{
_isDown = true;
_startPoint = Mouse.GetPosition((IInputElement)sender);
selectedElement = e.Source as UIElement;
_originalLeft = Canvas.GetLeft(selectedElement);
_originalTop = Canvas.GetTop(selectedElement);
aLayer = AdornerLayer.GetAdornerLayer(selectedElement);
aLayer.Add(new ResizingAdorner(selectedElement));
selected = true;
e.Handled = true;
}
Debug.WriteLine("Selected Value: " + selected);
}
从我在博客上找到的解决方案。我删除了代码中的所有代码,然后离开了这个
// Handler for element selection on the canvas providing resizing adorner
void myCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Remove selection on clicking anywhere the window
if (selected)
{
selected = false;
if (selectedElement != null)
{
// Remove the adorner from the selected element
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = null;
}
}
// If any element except canvas is clicked,
// assign the selected element and add the adorner
if (e.Source != myCanvas)
{
_isDown = true;
_startPoint = e.GetPosition(myCanvas);
selectedElement = e.Source as UIElement;
_originalLeft = Canvas.GetLeft(selectedElement);
_originalTop = Canvas.GetTop(selectedElement);
aLayer = AdornerLayer.GetAdornerLayer(selectedElement);
aLayer.Add(new ResizingAdorner(selectedElement));
selected = true;
e.Handled = true;
}
}
可以从顶部,左侧,右侧按钮调整绘制的控件。
但是我的代码。当我从左上角调整大小时。
它没有从那里调整大小。它做什么调整宽度和高度。不是矩形的左上角
这是绘制的矩形
当我从顶部调整大小时会发生这种情况。它调整了右下角而不是左上角
答案 0 :(得分:1)
我认为如果您在没有任何修改的情况下使用它,则问题出在ResizingAdorner
类中。无论绑定如何,该类都会直接修改关联元素的大小和Canvas
坐标。这意味着当您拖动左上角时,元素的大小已正确更改(因为Width
和Height
属性已被修改),但代码会尝试设置Canvas.Left
和Canvas.Right
并不起作用,因为整个Rectangle
位于ContentPresenter
(ItemsControl
的项容器)内。只有ContentPresenter
才能真正影响该职位,因为它是Canvas
的直接子女。在Canvas.Left
上设置Canvas.Right
和Rectangle
无效,因为没有Canvas
可以访问这些值。
要解决此问题,您必须抓住RectItem
类中的ResizingAdorner
实例 - 可能使用DataContext
:
var rectItem = adornedElement.DataContext as RectItem;
现在,您可以修改rectItem
属性,而不是Width
中Height
,Canvas.Left
,Canvas.Top
和ResizingAdorner
的所有现有引用} class。