Передача коллекции коллекций в TextBlock

97
06 февраля 2021, 06:20

Я думаю название уже звучит глупо, но давайте разберемся. Суть такова, что мне в столбец DataGrid'а нужно передать коллекцию коллекций, но не просто коллекцию, а вывести все ее элементы. Сейчас объясню. Есть класс Word и класс MeaningGroup

public class Word
{
    public String Name { get; set; }
    public List<MeaningGroup> MeaningGroups { get; set; }
}
public class MeaningGroup
{
    public List<string> Synonyms { get; set; }
    public List<string> Acronyms { get; set; }
}

И вот такая разметка в xaml

    <Grid>
            <DataGrid ItemsSource="{Binding Words}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                    <DataGridTemplateColumn x:Name="ListColumn" Header="Synonym and acronyms">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel>
                                   <TextBlock Text="{Binding Path=Synonyms}"/>
                                   <TextBlock Text="{Binding Path=Acronyms}"/>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>

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

        Word word1 = new Word() { Name = "word1",MeaningGroups = new List<MeaningGroup>() {group1, group2}};
        Word word2 = new Word() { Name = "word2", MeaningGroups = new List<MeaningGroup>() { group1, group2 } };
        Word word3 = new Word() { Name = "word3", MeaningGroups = new List<MeaningGroup>() { group1, group2} };
        Word word4 = new Word() { Name = "word4", MeaningGroups = new List<MeaningGroup>() { group1, group2 } };
        Words = new List<Word> {word1, word2, word3, word4};

В первый столбец мы передаем название, что сделать нетрудно забиндив Name, но вот что делать со столбцом, в который мы передаем List? Надо сделать так, чтобы в данный столбец ("ListColumn") мы передавали список MeaningGroup, в котором чтобы group1 и group2 были на разных строках, что я и сделал, добавив два текстблока. Нужно чтобы в первый текстблок передавались все элементы из коллекции group1, а во второй текстблок передавались все элементы из коллекции group2. Если я плохо объяснил, то попробую составить краткий план:

  1. Передать в DataGrid коллекцию List<Word> Words
  2. В столбец ListColumnпередавать List<MeaningGroup>, состоящий из group1 и group2
  3. В первый TextBlock передать все элементы из коллекции group1, во второй TextBlock передать все элементы из коллекции group2.

Я, может, и сам разберусь, но мне нужна помощь в том, как вообще в текстблок передать коллекцию элементов , чтобы он вывел у себя каждый элемент (еще и желательно бы с пробелом) т.е например если мы передаем ему коллекцию List<string> group1 с элементами {"Курица", "Баклажан", "Сосиска"} чтобы его текст был "Курица баклажан сосика"?

Answer 1

По сути тут два варианта:

  1. Отображать коллекцию так, как положено. Для этого в WPF существуют элементы ItemsControl, которые легко настраиваются так, как вам нужно. Я не буду особо вдаваться в подробности что да как, просто покажу как это использовать на вашем примере:

    <DataGridTemplateColumn x:Name="ListColumn" Header="Synonym and acronyms">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <StackPanel>
                    <ItemsControl ItemsSource="{Binding MeaningGroups}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <ItemsControl ItemsSource="{Binding Synonyms}">
                                        <ItemsControl.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <WrapPanel/>
                                            </ItemsPanelTemplate>
                                        </ItemsControl.ItemsPanel>
                                        <ItemsControl.ItemTemplate>
                                            <DataTemplate>
                                                <TextBlock Margin="3,3,3,3" Text="{Binding}"/>
                                            </DataTemplate>
                                        </ItemsControl.ItemTemplate>
                                    </ItemsControl>
                                    <ItemsControl ItemsSource="{Binding Acronyms}">
                                        <ItemsControl.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <WrapPanel/>
                                            </ItemsPanelTemplate>
                                        </ItemsControl.ItemsPanel>
                                        <ItemsControl.ItemTemplate>
                                            <DataTemplate>
                                                <TextBlock Margin="3,3,3,3" Text="{Binding}"/>
                                            </DataTemplate>
                                        </ItemsControl.ItemTemplate>
                                    </ItemsControl>
                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

То есть мы в ячейке сделали ItemsControl, который привязали к MeaningGroups и дальше под каждую коллекцию создали еще по одному ItemsControl со своим шаблоном (отступ), а также с расположением элементов в ряд (с помощью WrapPanel, либо любой другой). Как видите код повторяется и не очень удобен, поэтому все нужное стоит вынести в отдельный стиль и его уже использовать.

  1. Преобразовывать коллекцию в string. Тут вариантов уйма, решайте сами что и как вам будет удобней. Можно создать конвертер; можно создать отдельно свойство, где в get будет выдаваться нужный текст; а можно и вовсе переопределить .ToString и там уже вывести что нужно. Я покажу вариант с доп. свойствами:

    • Свойства:

      public string SynonymsString => Synonyms != null ? string.Join(" ", Synonyms) : null;
      public string AcronymsString => Acronyms != null ? string.Join(" ", Acronyms) : null;
      
    • XAML:

      <DataGridTemplateColumn x:Name="ListColumn" Header="Synonym and acronyms">
          <DataGridTemplateColumn.CellTemplate>
              <DataTemplate>
                  <StackPanel>
                      <ItemsControl ItemsSource="{Binding MeaningGroups}">
                          <ItemsControl.ItemTemplate>
                              <DataTemplate>
                                  <StackPanel>
                                      <TextBlock Text="{Binding SynonymsString}"/>
                                      <TextBlock Text="{Binding AcronymsString}"/>
                                  </StackPanel>
                              </DataTemplate>
                          </ItemsControl.ItemTemplate>
                      </ItemsControl>
                  </StackPanel>
              </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
      

В общем вариантов решения этой задачи уйма, выбирайте свой. Удачи!

READ ALSO
Несколько Form и подключение к базе данных

Несколько Form и подключение к базе данных

В программе несколько форм и каждой так или иначе нужна БД (через класс посредник) для наполнения или записи полученных данных

101
OnCollisionEnter2D для наследника

OnCollisionEnter2D для наследника

У меня есть абстрактный класс:

95
Входная строка имела неверный формат в Int32.Parse

Входная строка имела неверный формат в Int32.Parse

Столкнулся со странной ошибкойЕсть кнопка button, и событие Click для неё

131
Создать XML для Excel с помощью LINQ to XML

Создать XML для Excel с помощью LINQ to XML

Пытаюсь построить XML для Excel такого вида:

118