我正在使用 MVVM Light 在 WPF 中编写一些数据可视化代码。这是一个片段:
<Window x:Class="EventBlockVisualization.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:ignore="http://www.ignore.com"
Title="MainWindow"
mc:Ignorable="d ignore"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ItemsPanelTemplate x:Key="GraphRowItemsPanelTemplate">
<StackPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid IsSharedSizeScope="True">
<ScrollViewer Margin="8" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True">
<ItemsControl x:Name="GraphItemsControl" Margin="8" ItemsSource="{Binding VibeEvents, Mode=OneTime}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="NameWidthSizeGroup" Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="NameTextBlock" Text="{Binding Name}" Grid.Column="0" Margin="4,0"/>
<ItemsControl x:Name="GraphRowItemsControl" ItemsSource="{Binding VibeEventViewModels, Mode=OneTime}" ItemsPanel="{DynamicResource GraphRowItemsPanelTemplate}" Grid.Column="1" Margin="4,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" VerticalAlignment="Center" Height="10">
<TextBlock x:Name="FGTitleTextBox" Text="{Binding FGTitle}" Visibility="Collapsed"/>
<Button Margin="1,0,0,0" Width="{Binding LengthInSeconds}" HorizontalAlignment="Left" Background="{Binding BackgroundColor}" BorderBrush="#FF2186A1">
<Button.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock FontWeight="Bold" Text="{Binding FGTitle}"/>
<TextBlock Text="{Binding LengthText}"/>
</StackPanel>
</ToolTip>
</Button.ToolTip>
</Button>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>
我想换掉中央ItemsControl.ItemTemplate
DataTemplate
并使其成为用户控件,以便我可以在 Expression Blend 中更轻松地设计它。
我在 MVVM Light 中找不到包含用户控件的简单示例,但有一些教程文章。例如,在MVVM 实例化方法(选项 6)中,Paul Stovell 建议在 MVVM Light 中的 UserControl 的 ViewModel 中进行绑定,因此:
<UserControl ...>
<UserControl.Resources>
<ViewModelLocator x:Key="ViewModelLocator"/>
</UserControl.Resources>
<TextBox Text="{Binding Source={DynamicResource ViewModelLocator}, Path=CalculatorViewModel...}" />
当我在 Expression Blend 中设计 UserControl 时,这将非常有用,因为定位器可以提供一个充满虚拟数据的 ViewModel。但是在运行时会发生什么;该绑定如何被主 ViewModel 中的集合提供的 UserControl 的 ViewModel 类的实例覆盖?MainWindow 在设计时也会出现同样的问题。如果我在 MainWindow 的外观和感觉上使用 Expression Blend,该绑定如何被设计时主 ViewModel 中的集合提供的 UserControl 的 ViewModel 类的实例覆盖?
有许多问题和答案已经涉及到这一点:
在https://stackoverflow.com/a/3334780/575530中,akjoshi 建议主 ViewModel 包含 UserControl 的 ViewModel 的实例;但是当我设计 UserControl 本身时,它是如何工作的?
在https://stackoverflow.com/a/9910298/575530中,tam 指出“您希望保持数据上下文打开并可用于绑定到您使用此控件的控件”,并且在以下评论中 SoMoS 补充说需要“在 ViewModel 中为绑定的属性创建属性,当有人想要更改控件的一个属性(如启用某些子控件)时,他将不得不通过 View Model”。这是有希望的,但我不确定要做什么来代替 MainViewModel 的 UserControlViewModel 的可绑定集合。
在https://stackoverflow.com/a/6340668/575530中,Ehsan Ershadi 建议“对 UserControles 使用 MVVM Light ViewModelLocator 不是一个好主意,因为它是一个静态属性,并且当您要实例化用户控件的多个实例时将有相同的通用 ViewModel,因此它们的行为都相同,如果您决定在整个项目中使用一次,这不是我们想要的 UserControl。” 然后声明“要解决这个问题,您需要修改 ViewModelLocator,例如将所有属性设为非静态”。我不确定这对我有什么帮助。
在https://stackoverflow.com/a/2637830/575530之后的评论中, Jon Mitchell 提到“看起来 MVVM 确实不适合创建用户控件”。我希望那是不对的。
相反,在什么时候应该使用 UserControl 而不是 Page?dthrasher 提到“许多 WPF MVVM 框架似乎避免使用 NavigationWindow 和 Page 控件,而是使用嵌套的 UserControls 来编写页面”,即 UserControls 是 MVVM 中的常见设备。
在https://stackoverflow.com/a/1798649/575530中,Reed Copsey 提醒沙箱“UserControls 始终可以通过公开属性和使用 DataBinding 与其包含的控件对话。这非常好,因为它在各个方面都保留了 MVVM 样式。 " 并且“包含控件可以使用属性将两个用户控件上的两个属性链接在一起,再次保持干净的边界”但是当我在 Expression Blend 中设计 UserControl 时,我看不出这有什么帮助。
在我应该为我的视图使用 UserControls 而不是 DataTemplates 吗?Rachel 提到偶尔会在将代码剪切并粘贴到 DataTemplate 之前使用 Expression Blend 来设计 UserControl:“如果我确实想用它来设计 DataTemplate,我通常会创建一个新的 UserControl,按照我想要的方式设计它,然后将内容复制/粘贴到 DataTemplate"
对不起这个论文长度问题!在设计一个注定要成为 MainWindow 上集合中项目的视觉对象的 UserControl 时,我对如何使用 MVVM Light 感到困惑,尤其是如何设置三个绑定:运行时视图模型、主视图的设计时视图模型窗口及其用户控件的实例化,以及用于隔离用户控件的设计时视图模型。