ObservableCollection элементов управления - PullRequest
0 голосов
/ 09 марта 2020

Я работаю над программой, которая использует wpf с дизайном mvvm. У меня есть коллекция Control, каждый элемент может быть Button \ RadioButton \ TextBox ...

ObservableCollection<Control> controls_lst = new ...

Я хочу перебрать этот список по коду xaml представления, а также создать и отобразить каждый элемент управления. но проблема в том, что мне нужно проверить тип прежде, чем я напишу

, есть способ перебрать этот список и создать и отобразить элемент управления, проверив тип из xaml ? я

1 Ответ

0 голосов
/ 11 марта 2020
  1. Вы никогда не должны определять коллекции элементов управления или любой другой элемент пользовательского интерфейса. Если эта коллекция определена в модели представления, это также приведет к нарушению шаблона MVVM . Набор элементов управления исключает всю гибкость для динамического создания элементов управления.

    Рекомендованным способом является определение моделей элементов и предоставление им возможности динамического рендеринга с помощью соответствующих DataTemplpate и ItemsControl:

    Определения модели данных

    // Common base type
    interface ISelectorItem
    {
      public string Text { get; set; }
    }
    
    // Model to represent a ToggleButton
    class BooleanItem : ISelectorItem
    {
    }
    

    ViewModel.cs

    class ViewModel
    {
      public ObservableCollection<ISelectorItem> DataModels { get; set; }
    
      public ViewModel()
      {
        this.DataModels = new ObservableCollection<ISelectorItem>() { new BooleanItem() { Text = "Click Me"}};
      }
    }
    

    MainWindow.xaml

    <Window>
      <Window.DataContext>
        <ViewModel />
      </Window.DataContext>
    
      <Window.Resources>
        <DataTemplate DataType="{x:Type BooleanItem}">
          <ToggleButton Content="{Binding Text}" />
        </DataTemplate>
      </Window.Resources>
    
      <ListView ItemsSource="{Binding DataModels}" />
    </Window>
    

Вы можете использовать DataTrigger в сочетании с пользовательским преобразователем типов (также работает с решением 1):

Реализация TypeConverter (IValueConverter)

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
  => value.GetType();

Просмотр реализации

<ListView ItemsSource="{Binding CollectionWithControls}">
  <ListView.Resources>
    <TypeConverter x:Key="TypeConverter" />
  </ListView.Resources>
  <ListView.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=., Converter={StaticResources TypeConverter}} 
                     Value="{x:Type RadioButton}">
          <Setter ... />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  <ListView.ItemContainerStyle>
</ListView>

Использование DataTemplate:

<ListView ItemsSource="{Binding CollectionWithControls}">
  <ListView.Resources>
    <DataTemplate DataType="{x:Type RadioButton}">

      <!-- Type specific layout -->
      ...
    </DataTemplate>
  </ListView.Resources>
</ListView>
...