Динамическое добавление пользовательских элементов управления в WPF / MVVM - PullRequest
0 голосов
/ 28 апреля 2020

Возможно ли динамическое добавление и привязка пользовательских элементов управления? Может быть, я покажу пример кода, чтобы показать, что я имею в виду.

MainWindow:

 <UniformGrid
    Rows="11"
    Columns="11"
    DataContext="{StaticResource vm}">

    <local:DynamicUserControl
        ButClickControl="{Binding Path=UserControlObjects[0].ButClickCommand}"
        SomeDataInUserControl="{Binding Path=UserControlObjects[0].SomeData, Mode=OneWay}" />

    <local:DynamicUserControl
        ButClickControl="{Binding Path=UserControlObjects[1].ButClickCommand}"
        SomeDataInUserControl="{Binding Path=UserControlObjects[1].SomeData, Mode=OneWay}" />

    <local:DynamicUserControl
        ButClickControl="{Binding Path=UserControlObjects[2].ButClickCommand}"
        SomeDataInUserControl="{Binding Path=UserControlObjects[2].SomeData, Mode=OneWay}" />

    .....


</UniformGrid>

В ViewModel это массив UserControlObjects. Но в этом массиве будет более 100 элементов, так что это не лучший вариант записать все элементы по одному. Итак, есть ли способ добавить DynamicUserControls не в XAML, а где-нибудь в коде в l oop с сохранением шаблона MVVM и привязки?

Ответы [ 3 ]

2 голосов
/ 28 апреля 2020

По моему мнению, вы хотели бы не использовать какие-либо элементы управления в вашей модели представления. Однако можно сохранить отдельные модели представлений, поддерживающие элементы управления, в списке в рамках модели основного представления. Например, создайте модель представления, которая будет предоставлять данные для «динамических» элементов управления.

   class SubViewModel
   {
      public string Name { get; private set; } = string.Empty;

      public SubViewModel(string aName)
      {
         Name = aName;
      }
   }

И в модели основного представления вы можете делать все, что бы вы ни делали, для динамического создания экземпляров. В этом случае я просто создаю в a for l oop.

   class MainWindowViewModel
   {
      public ObservableCollection<SubViewModel> SubViewModels
      {
         get
         {
            return mSubViewModels;
         }
      } private ObservableCollection<SubViewModel> mSubViewModels = new ObservableCollection<SubViewModel>();

      public MainWindowViewModel()
      {
         for(int i = 0; i < 30; i++)
         {
            SubViewModels.Add(new SubViewModel($"Control: {i}"));
         }
      }
   }

Затем в представлении вы можете использовать ItemsControl с ItemsPanelTemplate на основе UniformGrid, а затем все, что вы хотите для данных. шаблон, определяете ли вы его там явно, или создаете пользовательский элемент управления (например, локальный: DynamicUserControl) для очистки. В этом примере шаблон данных явно определен.

<Window x:Class="ListOfViewsSample.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:local="clr-namespace:ListOfViewsSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
   <Window.DataContext>
      <local:MainWindowViewModel/>
   </Window.DataContext>
   <Grid>
      <ItemsControl ItemsSource="{Binding SubViewModels}">
         <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
               <UniformGrid/>
            </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
         <ItemsControl.ItemTemplate>
            <DataTemplate>
               <Grid Background="LightGray" Margin="10">
                  <Label Content="{Binding Name}" Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
               </Grid>
            </DataTemplate>
         </ItemsControl.ItemTemplate>
      </ItemsControl>
   </Grid>
</Window>

, что приводит к следующему:

enter image description here

Если не Если вы хотите, чтобы несколько динамических представлений c были одинаковыми, вы можете просмотреть селекторы шаблонов данных, чтобы отобразить что-то другое в зависимости от заданной модели представления, но, основываясь на вашем вопросе, я думаю, что вы искали список одного и того же элемента управления / данные. Надеюсь, это поможет!

2 голосов
/ 28 апреля 2020

Использование ItemsControl с UniformGrid в качестве ItemsPanel и DynamicUserControl в ItemTemplate:

<ItemsControl DataContext="{StaticResource vm}"
              ItemsSource="{Binding UserControlObjects}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="11" Columns="11"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:DynamicUserControl
                ButClickControl="{Binding ButClickCommand}"
                SomeDataInUserControl="{Binding SomeData}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
1 голос
/ 28 апреля 2020

Обычный способ сделать это:

  1. Создать ItemsControl для динамических c элементов, которые вы хотите создать
  2. Переопределите ItemsPanel на все, что вам нужно (UniformGrid в ваш случай)
  3. Свяжите его со списком моделей представлений, с одной моделью представления на элемент управления
  4. Определите шаблоны данных для сопоставления каждого типа модели представления с соответствующим типом представления
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...