DevD9 Ответов: 4

Привязка списка словарей в WPF DataGrid элемент управления во время выполнения


Здравствуйте, я работаю над одним заданием, используя WPF и MongoDB. Мне нужно сгенерировать WPF DataGrid (любой другой элемент управления будет в порядке, если он работает) во время выполнения из списка словаря<string,string>. Это простой словарь коллекции, где каждый словарь имеет свой набор пар клавиш.

До сих пор я могу генерировать столбцы во время выполнения из словаря<string,string> имеющего наибольшее количество столбцов. После генерации всех столбцов задача состоит в том, чтобы поместить данные в DataGrid и отобразить их.

Список словаря< string, string & gt; содержит различный набор столбцов в каждом словаре, когда я пытался использовать DataContext и ItemsSource DataGrid, но он генерирует пустой ГИРД.

Пожалуйста, поделитесь своими мыслями

4 Ответов

Рейтинг:
2

DevD9

Спасибо. Вот как я решаю эту проблему.

table = new DataTable();
            dgSearchResult.Columns.Clear();
            string broker = string.Empty;
            string producttype = string.Empty;
            string currency = string.Empty;
            string productsubtype = string.Empty;

            if (cmbProductTypes.SelectedValue != null)
                producttype = cmbProductTypes.SelectedValue.ToString();
            else
                producttype = "";

            if (cmbBrokers.SelectedValue != null)
                broker = cmbBrokers.SelectedValue.ToString();
            else
                broker = "";

            if (cmbProductSubtype.SelectedValue != null)
                productsubtype = cmbProductSubtype.SelectedValue.ToString();
            else
                productsubtype = "";

            if (cmbCurrency.SelectedValue != null)
                currency = cmbCurrency.SelectedValue.ToString();
            else
                currency = "";
//Sample is a list of dict of string string
            List<dictionary><string,string>> sample = Models.RateCards.GetCard(producttype,broker,productsubtype,currency);

            foreach (Dictionary<string,> d in sample)
            {
                foreach (string key in d.Keys)
                {
                    Addcolumn(key);
                }

            }

            foreach (Dictionary<string,> d in sample)
            {
                //Addrow(d);

                row = table.NewRow();
                foreach (KeyValuePair<string,> keyValue in d)
                {
                    if (table.Columns.Contains(keyValue.Key))
                    {
                        if (keyValue.Key != "XMLDefinition")
                        {
                            if (keyValue.Value.Contains(","))
                            {
                                //if (keyValue.Key == "Volume Band Rates" || keyValue.Key == "Premium Band Rates")
                                    row[keyValue.Key] = RemoveSpecialCharacters(keyValue.Value.Replace("}, ", "}" + System.Environment.NewLine).Replace(",", ";").Replace("{", "").Replace("}", "").Replace("[", "").Replace("]", "").Replace("''", ""));
                                //else
                                //    row[keyValue.Key] = RemoveSpecialCharacters(keyValue.Value.Replace(",", ";").Replace("{", "").Replace("}", "").Replace("[", "").Replace("]", "").Replace("''", ""));
                            }
                            else
                                row[keyValue.Key] = RemoveSpecialCharacters(keyValue.Value);
                        }
                        else
                            row[keyValue.Key] = keyValue.Value;
                    }
                }

                table.Rows.Add(row);

            }
            
            dgSearchResult.ItemsSource= table.DefaultView;
            
       }

       private static string RemoveSpecialCharacters(string str) 
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in str) 
            {
                if (c != '"') 
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }

        private void Addcolumn(string columnname)
        {
            if (!table.Columns.Contains(columnname))
            {

                DataGridTextColumn dgColumn = new DataGridTextColumn();
                dgColumn.Header = columnname;
                dgColumn.Binding = new Binding(string.Format("[{0}]", columnname));
                dgColumn.SortMemberPath = columnname;
                dgColumn.IsReadOnly = true;
                
                dgSearchResult.Columns.Add(dgColumn);
                
                DataColumn dtcolumn = new DataColumn();
                dtcolumn.Caption = columnname;
                dtcolumn.ColumnName = columnname;
                
                table.Columns.Add(dtcolumn);
                if (columnname == "_id" || columnname == "XMLDefinition")
                    dgColumn.Visibility = Visibility.Hidden;
                    
            }
        }</dictionary>


Рейтинг:
1

Member 12805636

Это то, что я использую для преобразования списка словарей в datatable(кредит кому-то на StackOverflow), к которому может привязаться datagrid.
N. B если T не является типом значения, то вам нужно будет указать свойство (представляющее интерес).

public static DataTable ToDataTable<T>(string tableName, Dictionary<string, IEnumerable<T>> dictionary, string property="")
     {
         Type myType = null;
         DataTable dataTable = new DataTable(tableName);
         DataRow row;
         System.Reflection.PropertyInfo myPropInfo = null;
         bool isValueType = typeof(T).IsValueType;
         if (!isValueType)
         {
             myType = typeof(T);
             myPropInfo = myType.GetProperty(property);

         }

         int length = 0;
         int i;
         List<System.Collections.IEnumerator> Enumerators = new List<System.Collections.IEnumerator>();

         var t = isValueType ? typeof(T) : myPropInfo.PropertyType;

         foreach (KeyValuePair<string, IEnumerable<T>> pair in dictionary)
         {

             var x = new DataColumn(pair.Key, t);

             dataTable.Columns.Add(x);


             Enumerators.Add(pair.Value.GetEnumerator());
             length++;

         }



         while (length > 0)
         {
             row = dataTable.NewRow();

             i = 0;
             foreach (KeyValuePair<string, IEnumerable<T>> pair in dictionary)
             {

                 if (Enumerators[i].MoveNext())
                     row[i] = isValueType ? Enumerators[i].Current : myPropInfo.GetValue(Enumerators[i].Current, null);

                 else
                     length--;

                 i++;

             }
             dataTable.Rows.Add(row);
         }

         return dataTable;
     }


Graeme_Grant

Это вопрос 5-летней давности. Вы действительно думаете, что он все еще ждет ответа? Пожалуйста, не отвечайте на надгробные вопросы,только на текущие нерешенные.

Member 12805636

Нет, я так не думаю, но wpf не слишком изменился за последние 5 лет. И этот вопрос актуален и сегодня. Так что он предназначался не для того, кто задал этот вопрос, а для любого другого, кто, как и я, наткнулся на этот уголок паутины. Проблема с ним заключается в том, что он упускает некоторые детали/ ошибается:

Это преобразует словарь в datatable, к которому можно привязать datagrid. Прямая привязка словаря в этом сценарии невозможна.






Рейтинг:
0

theHollow

Привет
Я бы прежде всего выбрал ObservableCollection вместо списка.
Это происходит потому, что этот список наследует интерфейс ICollectionChanged, так что изменения в коллекции будут появляться в пользовательском интерфейсе при привязке к коллекции из свойства ItemSource в datagrid.

Во-вторых, я бы не стал использовать словарь для хранения данных. Я бы создал класс со свойствами для всех " ключей "или" столбцов", из которых я создаю ObservableCollection.

Когда все это будет сделано, я бы использовал модель MVVM (мой личный выбор), но есть много альтернатив. И я бы использовал привязку в XAML из ItemSource к свойству в модели, содержащему ObservableCollection моих значений. Я думаю, что это быстрый и простой способ решить проблему.

Надеюсь, это поможет!


Рейтинг:
0

Oleksandr Kulchytskyi

Ну очевидно
Возможно, вам придется заменить его List<Dictionary<string,string>> для более удобной коллекции WPF ObservableCollection<IList<KeyValueHolder>> Предметы ,
где KeyValueHolder - это siple entity, см.:

public class KeyValueHolder
{
 public string Key {get;set;}
 public string Value {get;set;}
} 
.

Но один момент, чтобы рассмотреть, по своей природе ObservableCollection не является Thraed-безопасным!!

Итак, в вашем сценарии, я думаю , было бы прафарабельно реализовать подход master-details (у вас будет 2 сетки данных: - первая общая, представляющая количество ваших словарей, а вторая детализированная списком KeyValueHolder)


Vdovenko Andrei

Ивановичу Кульчицкому Александру , половину дня я искал в инете о том, как динамически перечислять<string & gt; В DataGrid. Ваше решение чертовски крутое, рабочее и одно из самых четких, которые я видел в своей жизни; большое спасибо, Александр Кульчицкий !!!