Как получить правильное имя сопоставления из источника привязки, привязанного к List<T> или анонимному типу, для использования в DataGridTableStyle?
-
05-07-2019 - |
Вопрос
Я пытаюсь создать объект DataGridTableStyle, чтобы можно было контролировать ширину столбцов DataGrid.Я создал объект BindingSource, привязанный к списку.На самом деле он привязан к списку анонимных типов, созданному с помощью Linq, следующим образом (имена переменных изменены для ясности того, что я делаю):
List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.
var query = from i in myList
select new
{
i.FieldA,
i.FieldB,
i.FieldC
};
myBindingSource.DataSource = query;
myDataGrid.DataSource = myBindingSource;
Затем я создаю объект DataGridTableStyle и добавляю его в сетку данных.Однако он никогда не применяет настроенные мной свойства стиля таблицы, поскольку я не могу установить правильное свойство myDataGridTableStyle.MappingName.
Я искал в Google около получаса и продолжал видеть ссылки на один и тот же вопрос на множестве разных форумов (буквально один и тот же текст, как будто кто-то просто скопировал и вставил вопрос...Я ненавижу это...).В любом случае, ни одно из предложений не работает, как и говорит этот парень на всех других сайтах.
Итак, кто-нибудь здесь знает, что мне нужно установить для свойства MappingName, чтобы мой TableStyle действительно работал правильно?Откуда я могу взять имя?(Это не может быть пусто...это работает только с BindingSource, привязанным к DataTable или SqlCeResultSet и т. д.).
Я думаю, что может возникнуть проблема с использованием Linq для создания анонимной, более специализированной версии объектов только с теми полями, которые мне нужны.Должен ли я просто попытаться привязать BindingSource непосредственно к объекту List?Или, может быть, даже привязать DataGrid непосредственно к объекту List и вообще пропустить источник привязки.
Спасибо
PS — C#, Compact Framework v3.5
ОБНОВЛЯТЬ:
Я опубликовал ответ ниже, который решил мою проблему.Независимо от того, лучший это подход или нет, он сработал.Стоит заглянуть, если у вас та же проблема, что и у меня.
Решение
Я нашел способ заставить это работать.Разобью на части...
List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.
DataGridTableStyle myDataGridTableStyle = new DatGridtTableStyle();
DataGridTextBoxColumn colA = new DataGridTextBoxColumn();
DataGridTextBoxColumn colB = new DataGridTextBoxColumn();
DataGridTextBoxColumn colC = new DataGridTextBoxColumn();
colA.MappingName = "FieldA";
colA.HeaderText = "Field A";
colA.Width = 50; // or whatever;
colB.MappingName = "FieldB";
.
... etc. (lather, rinse, repeat for each column I want)
.
myDataGridTableStyle.GridColumnStyles.Add(colA);
myDataGridTableStyle.GridColumnStyles.Add(colB);
myDataGridTableStyle.GridColumnStyles.Add(colC);
var query = from i in myList
select new
{
i.FieldA,
i.FieldB,
i.FieldC
};
myBindingSource.DataSource = query.ToList(); // Thanks Marc Gravell
// wasn't sure what else to pass in here, but null worked.
myDataGridTableStyle.MappingName = myBindingSource.GetListName(null);
myDataGrid.TableStyles.Clear(); // Recommended on MSDN in the code examples.
myDataGrid.TablesStyles.Add(myDataGridTableStyle);
myDataGrid.DataSource = myBindingSource;
По сути, DataGridTableStyle.MappingName должен знать, с каким типом объекта он сопоставляется.Поскольку мой объект является анонимным типом (созданным с помощью Linq), я не знаю, что это такое, до момента выполнения.После того как я привяжу список анонимного типа к источнику привязки, Я могу использовать BindingSource.GetListName(null) для получения строкового представления анонимного типа.
Следует отметить одну вещь.Если бы я просто привязал myList (тип «myType») непосредственно к источнику привязки, я мог бы просто использовать строку «myType» в качестве значения для DataGridTableStyle.MappingName.
Надеюсь, это будет полезно другим людям!
Другие советы
Просто чтобы пополнить коллекцию ответов, уже находящихся на этой странице....
Я был просто разочарован этой же проблемой, пытаясь разработать свое первое приложение с использованием форм Windows и компактной платформы (для Windows Mobile 6.5).
Из комментария Марка Грэвелла выше я узнал, что действительно возможно получить MappingName во время выполнения, проверяя свойства DataGrid.Сделав это, я обнаружил, что при связывании моего List<MyType>
непосредственно к свойству DataSource DataGrid, DataGrid фактически искал DataGridTableStyle с MappingName
"List`1"
вместо любой комбинации List<MyType>
или MyType
...
Так...поместив «List`1» в имя сопоставления в редакторе коллекции DataGridTableStyle (во время разработки), я смог настроить столбцы и другие свойства без необходимости создавать их все во время выполнения.
Я просто надеюсь, что это добавит еще немного к уже предоставленным ответам.Спасибо всем за предоставление мне руководящих принципов.
Запрос возвращает IEnumerable<T>
для некоторых T
, но большинство источников привязки (кроме ASP.NET) требуют IList
(например, любой IList<T>
реализация) - попробуйте добавить .ToList()
- т.е.
myBindingSource.DataSource = query.ToList();
А BindingList<T>
может работать даже лучше (если он поддерживается в CF 3.5), поскольку он лучше поддерживает некоторые распространенные сценарии привязки;если вам это нужно (и предполагая BindingList<T>
существует в CF 3.5), вы можете добавить метод расширения:
static BindingList<T> ToBindingList<T>(this IEnumerable<T> data)
{
return new BindingList<T>(new List<T>(data));
}
затем позвоните:
myBindingSource.DataSource = query.ToBindingList();
Для полноты картины альтернатива IList
является IListSource
(или даже Type
для сценариев, использующих исключительно метаданные), поэтому DataSource
обычно набирается как object
;если бы не эта проблема, компилятор, вероятно, смог бы сообщить вам о проблеме (т.если DataSource
был определен как IList
).
Я последовал этому ответу и обнаружил, что MappingName всегда оказывается именем базового класса (myType в примере).
Таким образом, кажется, что размещение коллекции через BindingSource в любом случае решает проблему, и тогда нет необходимости в BindingSource.GetListName(null).
Также я не обнаружил необходимости в ToList() запросе, поскольку BindingSource также сделает это за вас.
Большое спасибо Джейсону Дауну за то, что он направил меня на правильный путь.
Я столкнулся с той же проблемой при настройке ширины столбца.После долгих исследований и разработок я изменил код, как показано ниже, и он работает нормально.Код:
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = dgCustom.DataSource.GetType().Name;
где dgCustom
это идентификатор DataGrid в dgCustom.DataSource.GetType().Name
который работает отлично.