Задать вопрос
@daniil14056

Как в wpf mvvc отобразить список элементов динамически?

Есть ComboBox с 2 допустим элементами. У каждого выбранного элемента есть свой список настроек, которые может состоять из различного множества ComboBox,TextBox, CheckButton.
Как это реализовать в viewmodel-е?
Вроде, это пару строк, если делать в самой View, а как сделать в ViewModel.
Как можно сам элемент передать в viewModel какой Binding="" надо написать.
Вот есть как этот gird передать в DataContext ?

Почему у панелей разметки нету свойства ItemsSource? Или есть какой-то аналог, что бы моно было динамически вставлять удалять. Как можно в разметки сделать с Stack Gird GroupBox то же что и как в List, но из разных элементов?

//пока вот так в viewModel/...
    swith(list[i]. ViewContainer{
       case CheckBox:
          v=new CheckBox(){}
          v.SetBinding(////);
             ///
          vs.Add(v);
 // и результат возвращаю в  ItemsControl ItemsSource ={Binding vs}
}

///////////////////

      public class SettingView
        {
            public string Name { get; set; }
            public TypeView ViewContainer { get; set; }
            public List<ItemData> Options { get; set; } 
            public enum TypeView
            {
                TextBox,
                ComboBox,
                CheckBox
            }
        }
    public class ItemData
    {
        public string Name { get; set;}
        public object Value { get; set;}
   }
  • Вопрос задан
  • 63 просмотра
Подписаться 1 Сложный Комментировать
Пригласить эксперта
Ответы на вопрос 1
WNeZRoS
@WNeZRoS
Со структурой как у вас не понятно как оно должно работать.
Если сделать ItemData типизированными, то всё становится проще - wpf может по типу выбирать подходящий DataTemplate, и значения мы получаем нужного типа, а не пойми что.

public class SettingViewHost
{
    public IReadOnlyCollection<SettingView>? Views { get; init; }
}

public class SettingView
{
    public string? Name { get; init; }
    public IReadOnlyCollection<ItemData>? Options { get; init; }
}

public class ItemData
{
    public string? Name { get; init; }
    public int GridRow { get; init; }
    public int GridColumn { get; init; }
}

public class BooleanItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
{
    public bool Value { get; set; }
}

public class StringItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
{
    public string Value { get; set; } = string.Empty;
}


Собираем SettingViewHost с любым количеством SettingView с разными внутренними настройками и закидываем во вью с такими шаблонами:

<DataTemplate DataType="{x:Type local:StringItemData}">
    <StackPanel Orientation="Vertical">
        <TextBlock Text="{Binding Name, Mode=OneTime}" />
        <TextBox Text="{Binding Value}" />
    </StackPanel>
</DataTemplate>

<DataTemplate DataType="{x:Type local:BooleanItemData}">
    <CheckBox Content="{Binding Name, Mode=OneTime}" IsChecked="{Binding Value}" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:SettingView}">
    <ItemsControl ItemsSource="{Binding Options}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid IsItemsHost="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="{x:Type ContentPresenter}">
                <Setter Property="Grid.Column" Value="{Binding GridColumn, Mode=OneTime}" />
                <Setter Property="Grid.Row" Value="{Binding GridRow, Mode=OneTime}" />
                <Setter Property="Margin" Value="4" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</DataTemplate>

<DataTemplate DataType="{x:Type local:SettingViewHost}">
    <StackPanel Orientation="Vertical">
        <ComboBox Name="ComboBox" ItemsSource="{Binding Views}">
            <ComboBox.ItemTemplate>
                <DataTemplate DataType="{x:Type local:SettingView}">
                    <TextBlock Text="{Binding Name, Mode=OneTime}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        
        <ContentControl Content="{Binding ElementName=ComboBox, Path=SelectedItem}" />
    </StackPanel>
</DataTemplate>


Пример сделан с Grid'ом 2х2, можно использовать любую панель. Обычный Grid для динамических целей не удобен т.к. у него фиксированное кол-во строк и столбцов. Лучше использовать UniformGrid или что-то ещё, или развлекаться с attached dependency property или MarkupExtension чтобы динамически генерировать строки и столбцы.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы