在过去的两天里,我一直坚持一个(简单?)问题.我在互联网上搜索了很多,但我找不到一个能够解决我完全情况的例子(每次遗漏一个方面,这是我自己实现的突破因素).
我想要什么:
创建我自己的WPF控件,它显示一个顶部矩形(或一般实际上是形状)的图像,在缩放和平移时保持固定.此外,这些矩形需要调整大小(尚未完成)并且可以移动(现在就做).
我希望这个控件能够遵循MVVM设计模式.
我有什么:
我有一个带有ItemsControl的XAML文件.这表示动态数量的矩形(来自我的ViewModel).它绑定到我的ViewModel(ObservableCollection)的RectItems.我想将项目渲染为矩形.这些矩形必须由用户使用他的鼠标移动.移动后,它应该在ViewModel中更新我的模型实体.
XAML:
<ItemsControl ItemsSource="{Binding RectItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding TopLeftX}"/>
<Setter Property="Canvas.Top" Value="{Binding TopLeftY}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Stroke="Black" StrokeThickness="2" Fill="Blue" Canvas.Left="0" Canvas.Top="0"
Height="{Binding Height}" Width="{Binding Width}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding ElementName=border,Path=DataContext.MouseLeftButtonUpCommand}" CommandParameter="{Binding}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding ElementName=border,Path=DataContext.MouseLeftButtonDownCommand}" CommandParameter="{Binding}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding ElementName=border,Path=DataContext.MouseMoveCommand}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)
视图模型:
public class PRDisplayViewModel : INotifyPropertyChanged
{
private PRModel _prModel; …Run Code Online (Sandbox Code Playgroud) 我的代码不绑定到可观察集合中项目的 X 和 Y 属性。怎么了:
<ItemsControl ItemsSource="{Binding LED}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="SkyBlue"/>
</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>
<Ellipse Stroke="{Binding Color}" Fill="{Binding FillColor}" StrokeThickness="1" Width="40" Height="40"></Ellipse>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
它确实绑定到颜色和填充颜色。这是 Shape 类,它存储在 ObservableCollection LED 中:
class Shape
{
public int X { get; private set; }
public int Y { get; private set; }
public string Color { get; private set; }
public string FillColor { get; …Run Code Online (Sandbox Code Playgroud) 我得到了一个ItemsControl使用Canvasas 的项目ItemsPanel,它的项目根据绑定类型呈现为不同的 WPF 形状,基本上如下所示:
<ItemsControl ItemsSource="{Binding PreviewShapes}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:UiPreviewLineViewModel}">
<Line X1="{Binding Start.X}" Y1="{Binding Start.Y}"
X2="{Binding End.X}" Y2="{Binding End.Y}"
StrokeThickness="0.75" Stroke="{Binding Brush}" x:Name="Line" ToolTip="{Binding Text}">
</Line>
</DataTemplate>
<DataTemplate DataType="{x:Type local:UiPreviewEllipsisViewModel}">
<Ellipse Canvas.Left="{Binding UpperLeft.X" Canvas.Top="{Binding UpperLeft.Y}"
Width="{Binding Width}" Height="{Binding Height}"
StrokeThickness="0.75" Stroke="{Binding Brush}" x:Name="Ellipse" ToolTip="{Binding Text}">
</Ellipse>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="SketchCanvas" ClipToBounds="False">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
因此,我基本上将对象添加到PreviewShapes视图模型中,并根据它们渲染到 WPFLine或Ellipses 的类型。这基本上可以工作,但附加的属性Canvas.Left和 …
我在画布中创建形状(矩形、椭圆、线条)。然后我在另一个窗口中有一个列表视图,我需要在其中输入形状的信息(例如位置、大小、它是什么形状)。
我在另一个窗口中的 XAML 中有此代码:
<ListView Name="Information">
<ListView.View>
<GridView>
<GridViewColumn Header="Type"/>
<GridViewColumn Header="PositionX"/>
<GridViewColumn Header="PositionY"/>
<GridViewColumn Header="Width" DisplayMemberBinding="{Binding ActualWidth}"/>
<GridViewColumn Header="Height" DisplayMemberBinding="{Binding ActualHeight}"/>
</GridView>
</ListView.View>
</ListView>
Run Code Online (Sandbox Code Playgroud)
在主窗口的 c# 中,我有一个可观察的集合和以下代码:
ObservableCollection<Shape> shapes = new ObservableCollection<Shape>();
myRect.Width = var1;
myRect.Height = var2;
Page.Children.Add(myRect);
Canvas.SetLeft(myRect, posx);
Canvas.SetTop(myRect, posy);
shapes.Add(myRect);
2ndwindow.Information.ItemsSource = shapes; // this is working because the 2ndwindow is owned by the mainwindow
Run Code Online (Sandbox Code Playgroud)
编辑:我设法绑定了宽度和高度,但我不知道如何绑定它的位置和形状(矩形或椭圆)