我有一个可工作的Prism WPF应用程序,其主要目标是工厂操作员的UI和与工厂机器的通信。
主UI视图(MachineDashboard
)绑定到其视图模型(MachineDashboardViewModel
),其中基于属性MachineId
完成与Machines和BL的所有通信。
此属性现在已从应用程序设置中初始化。
现在我需要升级应用程序,这样它将显示不同机器的UI(最多4台)。基本上,我需要显示多达4个不同的视图(MachineDashboard)。
我向UserControlMachineDashboard
MachineId_DP
添加了依赖属性,通过它我在ViewModelMachineDashboardViewModel
中设置属性MachineId
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="local:MachineDashboard">
<Setter Property="MachineId_DP" Value="{Binding MachineId, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
如果我想在HomeView中显示不同机器的UserCotrols,我现在可以添加用户控件并定义机器的Ids
<WrapPanel Grid.Row="0">
<local:MachineDashboard MachineId_DP="1" Margin="10"/>
<local:MachineDashboard MachineId_DP="2" Margin="10"/>
<local:MachineDashboard MachineId_DP="3" Margin="10"/>
<local:MachineDashboard MachineId_DP="4" Margin="10"/>
</WrapPanel>
这正是我想要的。
但若我尝试通过ItemsControl做同样的事情(因为机器的确切列表是从数据库加载的),MachineId
的绑定就不起作用了。已加载正确数量的用户控件,但MachineIds
未传递到MachineDashboardViewModel
<ItemsControl Grid.Row="1" ItemsSource="{Binding Machines}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate >
<local:MachineDashboard MachineId_DP="{Binding MachineId}" Margin="10"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
事实上,即使我尝试添加带有固定MachineId_DP参数的数据模板,结果也是一样的。
<DataTemplate >
<local:MachineDashboard MachineId_DP="3" Margin="10"/>
</DataTemplate>
我检查了每一个stackoverflow的条目,都有类似的问题,但没有适当的答案,通常争论的焦点是为什么要为用户控制设置viewmodel。这个用户控件(MachineDashboard)实际上由大约50个控件组成,如标签、数据网格、按钮等,并链接到其他输入对话框。因此,每台机器的视图模型的单独实例在这里是必须的。
此外,依赖性注入在MachineDashboardViewModel 中实现
public MachineDashboardViewModel(IDialogService dialogservice, ILogger logger)
因此,我要问的主要问题是如何动态加载用户控件MachineDashboard
,并在其视图模型中设置适当的MachineId
属性?
我创建了非常简化的示例应用程序此处
最简单的选项是在创建MachineDashboardViewModel
时在它们上设置MachineId
,并将它们放入Machines
属性中。
当子视图模型从一开始就处于父视图模型的属性中时,从父视图模型到数据模板到用户控件再到子视图模型的迂回是完全没有意义的。