在运行时添加控件的更好方法

时间:2020-08-26 22:04:00

标签: c# wpf mvvm

我正在寻找在运行时添加WPF控件的最佳方法。我会解释。

  • 应用程序启动时,我想搜索一些数据,并基于这些数据创建一些UI控件。

简单的例子

  • 启动应用程序
  • 搜索配置(在数据库中)
  • 根据配置创建或不创建某些控件。

以非MVVM方式,我简单地创建一个循环来创建或记录这些控件。但是我不知道如何在MVVM模式上做到这一点。

我最初的想法是创建所有可能的控件,并根据配置显示或不显示。这是最好的方法吗?

谢谢:)

1 个答案:

答案 0 :(得分:0)

我正在寻找在运行时添加WPF控件的最佳方法。

如果您不使用后台代码,我认为data templating正是您所需要的。

我希望该应用程序在数据库中检查列出了哪些布尔标签,并为每个标签创建一个切换按钮。

您可以使用ItemsControlDataTemplate来执行此操作。为您要显示的每种控件类型创建一个数据类,例如具有切换状态和标题的ToggleButton属性的bool。始终确保实施INotifyPropertyChanged以反映用户界面中数据的更改。

public class MyToggleDataType : INotifyPropertyChanged
{
   private bool _isToggled;
   private string _title;

   public bool IsToggled
   {
      get => _isToggled;
      set
      {
         if (_isToggled == value)
            return;

         _isToggled = value;
         OnPropertyChanged();
      }
   }

   public string Title
   {
      get { ... }
      set { ...}
   }

   public event PropertyChangedEventHandler PropertyChanged;

   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

公开要在主视图模型中显示为控件的所有数据项的集合。 ObservableCollection会自动通知更改,例如添加或删除项目。我使用了object的集合,但是您最好在这里使用数据项的基类。

public ObservableCollection<object> MyDataItems { get; }

您需要确保在用户界面中使用该集合之前先对其进行初始化,或者如果稍后分配它,则请实现INotifyPropertyChanged来表示更改。

在XAML中,为您在ItemsControl属性中指定的每种项目数据类型创建一个DataTemplate并添加一个DataTypeDataTemplate包含应显示的控件以及与相应数据项的所有绑定。将ItemsSource的{​​{1}}绑定到您的ItemsControl集合中。

MyDataItems

现在,您只需要从数据库中获取数据,将它们包装在相应的数据项中,或者使用这些数据类型,然后将它们添加到<ItemsControl ItemsSource="{Binding MyDataItems}"> <ItemsControl.Resources> <DataTemplate DataType="{x:Type local:MyDataType}"> <ToggleButton IsChecked="{Binding IsToggled}" Content="{Binding Title}"/> </DataTemplate> </ItemsControl.Resources> </ItemsControl> 集合中即可。每次添加项目时,集合都会通知更改,MyDataItems将搜索关联的数据模板并显示控件。

如果要使用单个控件执行此操作,则可以使用ItemsControl,其工作方式相同:公开视图模型属性,将其绑定到ContentControl属性并创建显示它的数据模板。对于需要创建复杂视图和导航的高级方案,您可能希望使用MVVM框架,例如Caliburn.Micro,Stylet或Prism,但我认为这不是您的范围。