【问题标题】:Binding to a collection of UserControl绑定到 UserControl 的集合
【发布时间】:2014-09-16 14:06:54
【问题描述】:

我有一个用 WPF (MVVM) 编写的应用程序,它会根据某些条件创建不同 UserControls 的实例,这些 UserControls 是完全独立的,用于显示某些信息。他们里面有一些自定义逻辑,比如计时器等等,所以我不能使用模板。

现在我面临的问题是我想在 ViewModel 中创建一个用户控件列表,并将主机 UI 绑定到它。问题是我不知道如何绑定和绑定什么。在非 MVVM 项目中,您只需获取要放置控件的布局,并将它们作为子项添加到那里。在 MVVM 应用程序中,我不知道该怎么做。我想象有一个带有 ItemsSource 的 WrapPanel,它将添加所有控件并根据需要根据 UserControls 调整自身大小。

有人可以提出解决方案吗?

编辑: 我的 ViewModel 现在公开了一个 IMyDriverObservableCollection。所以这就是我的想法,打破一点 MVVM 以获得我接下来描述的内容: 现在,每个 IMyDriver 都可以是不同类型的驱动程序,并且可以实现不同的其他接口。我需要 UI 来创建特定的用户控件,这些用户控件知道如何根据这些驱动程序的功能获得最大的收益。简而言之,UserControls通过驱动程序连接到设备,用于轮询数据。每个 UserControl 都以特定的方式进行操作。

【问题讨论】:

  • 我想在 ViewModel 中创建一个用户控件列表...不,不,不!这不是 MVVM 的工作原理,所以要么改变你的方法,要么从你的问题中删除那个MVVM 标签......你不能同时拥有它。
  • DataTemplates 将 VM 类型链接到 UserControls。巴姆。完成。
  • 威尔,这个答案以及谢里登的答案让我朝着正确的方向思考。非常感谢!

标签: wpf xaml mvvm user-controls


【解决方案1】:

您可以通过为每个UserControl 中的数据声明特定的数据类型类并在App.xaml 文件中定义公开UserControls 的DataTemplates 来非常简单轻松地做到这一点:

<DataTemplate DataType="{x:Type YourViewModelsPrefix:YourViewModel">
    <YourViewsPrefix:YourView />
</DataTemplate>
<DataTemplate DataType="{x:Type YourViewModelsPrefix:YourOtherViewModel">
    <YourViewsPrefix:YourOtherView />
</DataTemplate>
<DataTemplate DataType="{x:Type YourViewModelsPrefix:AnotherViewModel">
    <YourViewsPrefix:AnotherView />
</DataTemplate>

现在,每当框架遇到这些视图模型类的实例时,它都会渲染关联的视图/UserControl。您可以通过使用 ContentControl 拥有视图模型类型的属性来显示它们,如下所示:

<ContentControl Content="{Binding YourViewModelProperty}" />

...

public YourBaseViewModelClass YourViewModelProperty { get; set; }

确保您的所有视图模型都扩展了此类:

public YourViewModel : YourBaseViewModelClass { }
...
public AnotherViewModel : YourBaseViewModelClass { }

然后您可以像这样交换每个视图模型(并显示每个相关视图):

YourViewModelProperty  = new AnotherViewModel();

【讨论】:

    【解决方案2】:

    根据Will 的评论和Sheridan 的回答,我找到了解决问题的方法。

    所以:

    1. 我不会通过保持 ViewModel 类型不变来破坏 MVVM。

    2. 我在 Window 的 Resources 标记中创建 DataTemplate,在每个数据模板中,我将 DataTemplate 分配为我在另一个程序集 (UICommons) 中定义的 UserControl

      <DataTemplate x:Key="IMultiChannelMeasurementDCDataTemplate">
          <uicommon:MeasurementMax8ChannelMonitoringUserControl/>
      </DataTemplate>
      
    3. 我在我的应用程序程序集中创建了一个模板选择器,并且基于 DataTypes 实现的接口,我返回了正确的 DataTemplate,我在同一个窗口的资源标签中分配了它

          <!-- DataTemplate Selector -->
      <local:DriverComponentDataTemplateSelector x:Key="templateSelector"
            DefaultDCDataTemplate="{StaticResource DefaultDCDataTemplate}"
            IIhcDCDataTemplate="{StaticResource IIhcDCDataTemplate}" 
            IMultiChannelMeasurementDCDataTemplate="{StaticResource IMultiChannelMeasurementDCDataTemplate}"
            IProgrammablePowerSourceDCDataTemplate="{StaticResource IProgrammablePowerSourceDCDataTemplate}"
            IEnvDCDataTemplate="{StaticResource IEnvDCDataTemplate}"/>
      
    4. 我使用以下 XAML 代码在 Window 中创建了一个 ItemsControl,它将自身绑定到我的 ObservableCollection 项目

      <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
          <ItemsControl ItemTemplateSelector="{StaticResource templateSelector}" ItemsSource="{Binding DriverComponentsInfo}">
              <ItemsControl.ItemsPanel>
                  <ItemsPanelTemplate>
                      <WrapPanel Orientation="Horizontal" x:Name="ucWrapPanel">
                      </WrapPanel>
                  </ItemsPanelTemplate>
              </ItemsControl.ItemsPanel>            
          </ItemsControl>
      </ScrollViewer>
      
    5. 我喜欢基于不同驱动程序动态创建的用户控件!

    附:我赞成Will 的评论和Sheridan 的回答,因为没有这些,我将无法找到解决方案。谢谢!

    【讨论】:

      【解决方案3】:

      它们里面有一些自定义逻辑,比如计时器等等,所以我不能使用模板。

      这不符合。我认为您可能对 WPF 的功能有误解。

      另外,当您想使用 MVVM 时:绑定到 UserControls 的列表会破坏这种模式。视图模型应该只引用其他视图模型(和模型);他们对用户界面一无所知。绑定到将UserControls 关联为视图的视图模型集合(考虑使用implicit DataTemplates)。要绑定 WrapPanel,请使用 ItemsControl 并相应地设置其 ItemsPanel

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-14
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多