我一直在开发我的第一个MVVM应用程序,在该应用程序中,我想绘制一个包含节点和边的图表。目前,我正在执行视图后面的代码中的所有绘图逻辑,迭代节点,相应地创建形状并将它们添加到画布中。
因为我不想跟踪形状,只想根据给定的数据(即节点)绘制形状,所以我决定创建一个ObservableCollection,Nodes和Edges,并将ItemsControl绑定到这些数据,以便自动绘制形状。
目前,我的重点是绘制节点,并提出了以下XAML代码:
<ItemsControl x:Name="ItemsControlCanvas" ItemsSource="{Binding Path=Nodes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas>
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ?}" ScaleY="{Binding ?}"/>
</Canvas.LayoutTransform>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="Blue" Width="4" Height="4" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Path=Position.Y}" />
<Setter Property="Canvas.Left" Value="{Binding Path=Position.X}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>在我看来,我有两个属性ScaleX和ScaleY,这两个属性是当用户在画布上滚动时设置的。在我的早期版本代码中,我将使用这些属性创建一个ScaleTransform,并使用LayoutTransform将其应用到命名的画布中。
public partial class GraphOverview : Page
{
public double ScaleX { get; set; }
public double ScaleY { get; set; }这个版本的问题是,我无法让它在我的新XAML代码中工作。我希望将ScaleX和ItemsPanelTemplate中的ScaleTransform属性绑定到我的视图中的属性。只是,由于某些原因,普通的ElementName绑定无法工作。更清楚的是,我认为画布可能不知道视图,因为它是一个模板。此外,我不能从后面的代码调用画布,即使它有一个名称。
我尝试过几种解决方案,在RelativeResources等方面摸索,但我想我不明白为什么ItemsPanelTemplate与XAML代码中的其他所有东西都如此断开。提前感谢!
更新
也许我应该澄清,通过将ScaleX和ScaleY属性移动到ViewModel,并绑定到这些属性,可以很容易地解决这一问题。但在我看来,这种特定于视图的属性不应该驻留在ViewModel中。
发布于 2014-04-09 10:24:16
当您说视图特定信息不应该在视图模型中时,您是正确的。但是在您的情况下,这些位置成为模型的一部分,因为这些位置只不过是您的视图应该基于的数据。在这种情况下,您可以将它们视为模型的一部分,而不是视图。编写一个单独的模型类,并在ViewModel类的可观察集合中使用它。我希望这能消除你的疑虑。
public class Node
{
public double ScaleX { get; set; }
public double ScaleY { get; set; }
}编辑
回答你的问题。-
但是Scale属性指定画布的行为方式,那么View是否已经成为了这方面的“模型”呢?在我看来,创建一个新的模型来设置单个画布的比例属性似乎是多余的吗?视图应该仅仅关注绘图数据,而且由于属性作为这些绘图的修改,它们属于视图,不是吗?
您希望根据所提供的数据绘制图表。Node类将为您提供数据。它存储数据,而不是存储画布应该呈现的逻辑,XAML代码使用这些数据,并具有在视图中显示数据的逻辑。
,那么视图是否已经成为这方面的“模型”?
您尝试过的实现将模型包含在视图中,其思想是将模型与视图分开。最初创建一个类来容纳2个双值看起来可能是多余的。但是,如果你把它们从视野中抽离,就会有一些好处。
通常,ScaleX和ScaleY将是视图的一部分,但在您的示例中,它们会更改并存储数据。因此,您需要将这个ScaleX和ScaleY抽象到一个不同的层中,以保留MVVM的概念。
发布于 2014-04-09 00:28:03
我不确定您是否设置了视图的DataContext,这有助于在后面显示更多的代码
internal ViewModel viewModel { get; set; }
public View()
{
DataContext = (viewModel = new ViewModel());
}您是否将ObservableCollection绑定到节点的ItemSource?我不熟悉绘画,但是当我和孩子们在一起的时候,我从来没有取得过成果。
但是我只开发了大约4个使用MVVM的项目。
https://stackoverflow.com/questions/22949449
复制相似问题