Каждый DataRow в таблице содержит плоский массив объектов, тип которых доступен только путем извлечения его из массива DataColumns. Поскольку все в массиве упаковано, библиотека, основанная на строго типизированной коллекции, такой как List of T, не будет совместима. Это должно объяснить, почему он не работает.
Вы написали, что это срочно, и мне пришлось однажды сделать то же самое в проекте с очень коротким запалом, и я изложу свой подход. Этот ответ предназначен только для СРОЧНЫХ случаев.
Вот ViewModel...
public class ViewModel : INotifyPropertyChanged
{
public CollectionView MyCollectionView { get; set; }
public ViewModel(DataTable dataTable)
{
MyCollectionView = CollectionViewSource.GetDefaultView(dataTable.Rows) as CollectionView;
if (MyCollectionView != null)
{
MyCollectionView.Filter = o => (o as DataRow).ItemArray[0].ToString().Contains("2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
Конструктор берет DataTable и использует Rows в качестве источника привязки к CollectionView. Поскольку CollectionView имеет встроенные свойства фильтрации и сортировки, это отличный инструмент для использования в качестве источника привязки. Также, как показано, конструктор добавляет фильтр для примера, который поможет вам начать работу.
Чтобы представить данные пользователю, рассмотрите следующий Xaml...
<DataGrid ItemsSource="{Binding MyCollectionView}"
AutoGenerateColumns="False"
CanUserSortColumns="True"
IsReadOnly="True"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding ., Converter=
{db:DbConverter}, ConverterParameter=PersonName}"/>
<DataGridTextColumn Header="Address" Binding="{Binding ., Converter=
{db:DbConverter}, ConverterParameter=PersonAddress}"/>
</DataGrid.Columns>
</DataGrid>
Это DataGrid, ItemsSource которого привязан к CollectionView, который был объявлен и назначен в ViewModel. Каждый столбец данных проходит через преобразователь вместе с параметром, который сообщает преобразователю, что ему нужно делать.
В довершение всего, вот конвертер...
public class DbConverter : MarkupExtension, IValueConverter
{
private static readonly Dictionary<object, int> ParameterToColumnMapping;
static DbConverter()
{
ParameterToColumnMapping = new Dictionary<object, int>
{
{"PersonName", 0}, {"PersonAddress", 1}
};
}
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
DataRow dr = value as DataRow;
if (dr != null)
{
if (ParameterToColumnMapping.ContainsKey(parameter))
{
return dr.ItemArray[ParameterToColumnMapping[parameter]];
}
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
Это должно помочь вам вернуться к фильтрации и представлению, когда у вас есть DataTable и срочная ситуация. На все кодирование уходит около часа. Также обратите внимание, что мой привязывается к Rows, но вы также можете привязаться к DefaultView, если это необходимо.
25.06.2013