#wpf #datagrid #strongly-typed-dataset
#wpf #сетка данных #строго типизированный-dataset
Вопрос:
Я борюсь с использованием наборов данных с сеткой данных WPF. Привязка и заполнение сетки отлично работают и очень просты…просто создайте dataset datasource и перетащите его в окно. Вуаля! Но когда я пытаюсь прикрепить событие RowChanged к набору данных, я получаю сообщение об ошибке:
С этой командой уже связан открытый DataReader, который необходимо сначала закрыть.
Когда я помещаю точку останова внутри обработчика событий, по какой-то причине она вызывается дважды (как минимум), и при 2-м вызове возникает исключение с описанием выше. Для меня не имеет смысла, что он вызывается несколько раз.
Я читал, что я мог бы добавить «MultipleActiveResultSets = true» в свою строку подключения, но такое ощущение, что я неправильно использую функцию SQLServer, чтобы скрыть что-то, что я сделал неправильно.
Вот мой XAML:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test" x:Class="Test.MainWindow"
Title="MainWindow" Height="350" Width="1141" Loaded="Window_Loaded">
<Window.Resources>
<local:SentinelDBDataSet x:Key="sentinelDBDataSet"/>
<CollectionViewSource x:Key="changeEventViewSource" Source="{Binding ChangeEvent, Source={StaticResource sentinelDBDataSet}}"/>
</Window.Resources>
<Grid DataContext="{StaticResource changeEventViewSource}">
<DataGrid x:Name="changeEventDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="0
" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTextColumn x:Name="cameraIDColumn" Binding="{Binding CameraID}" Header="Camera ID" Width="SizeToHeader" IsReadOnly="True"/>
<!--<DataGridTextColumn x:Name="changeEventIDColumn" Binding="{Binding ChangeEventID}" Header="Change Event ID" IsReadOnly="True" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="backgroundID_RefColumn" Binding="{Binding BackgroundID_Ref}" Header="Background ID Ref" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="backgroundID_ChangeColumn" Binding="{Binding BackgroundID_Change}" Header="Background ID Change" Width="SizeToHeader"/>-->
<DataGridTemplateColumn x:Name="timeStampColumn" Header="Time Stamp" Width="SizeToHeader" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding TimeStamp, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="annotationColumn" Binding="{Binding Annotation}" Header="Annotation" Width="SizeToHeader" IsReadOnly="False"/>
<DataGridCheckBoxColumn x:Name="validatedColumn" Binding="{Binding Validated}" Header="Validated" Width="SizeToHeader" IsReadOnly="True"/>
<DataGridTextColumn x:Name="confidenceColumn" Binding="{Binding Confidence}" Header="Confidence" Width="SizeToHeader" IsReadOnly="True"/>
<!--<DataGridCheckBoxColumn x:Name="focusChangedColumn" Binding="{Binding FocusChanged}" Header="Focus Changed" Width="SizeToHeader"/>-->
<DataGridCheckBoxColumn x:Name="focusDeltaChangedColumn" Binding="{Binding FocusDeltaChanged}" Header="Focus Delta Changed" Width="SizeToHeader" IsReadOnly="True"/>
<!--<DataGridCheckBoxColumn x:Name="brightnessChangedColumn" Binding="{Binding BrightnessChanged}" Header="Brightness Changed" Width="SizeToHeader"/>-->
<DataGridCheckBoxColumn x:Name="correlationChangedColumn" Binding="{Binding CorrelationChanged}" Header="Correlation Changed" Width="SizeToHeader" IsReadOnly="True"/>
<DataGridCheckBoxColumn x:Name="edgeCorrelationChangedColumn" Binding="{Binding EdgeCorrelationChanged}" Header="Edge Correlation Changed" Width="SizeToHeader" IsReadOnly="True"/>
<DataGridCheckBoxColumn x:Name="edgeDensityChangedColumn" Binding="{Binding EdgeDensityChanged}" Header="Edge Density Changed" Width="SizeToHeader" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
И вот мой класс MainWindow:
public partial class MainWindow : Window
{
SentinelDBDataSet dataset;
SentinelDBDataSetTableAdapters.ChangeEventTableAdapter adapter;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
dataset = ((Test.SentinelDBDataSet)(this.FindResource("sentinelDBDataSet")));
// Load data into the table ChangeEvent. You can modify this code as needed.
adapter = new Test.SentinelDBDataSetTableAdapters.ChangeEventTableAdapter();
adapter.Fill(dataset.ChangeEvent);
System.Windows.Data.CollectionViewSource changeEventViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("changeEventViewSource")));
changeEventViewSource.View.MoveCurrentToFirst();
dataset.ChangeEvent.RowChanged = ChangeEvent_RowChanged;
}
void ChangeEvent_RowChanged(object sender, System.Data.DataRowChangeEventArgs e)
{
adapter.Update(dataset.ChangeEvent);
}
}
Любые советы будут с благодарностью. Если есть лучший способ управления для взаимодействия с наборами данных, я готов рассмотреть все, что поставляется с WPF. К сожалению, этот проект не будет поддерживать использование коммерческих инструментов, таких как Infragistics.
Брайан
Комментарии:
1.
I'm struggling with using datasets with a WPF datagrid
— Совершенно верно. Вы больше не должны использовать datasets в WPF. Они просто прославленныеDictionary<string,object>
, которые заставляют вас погружаться в ад нетипизированных вещей, постоянного кастинга и всего, что связано с магическими струнами. Создайте правильную реализацию строго типизированной объектной моделиINotifyPropertyChanged
, и все ваши проблемы волшебным образом исчезнут.2. @HighCore = спасибо за ваш совет. Похоже, мне нужно сделать шаг назад и, возможно, рассмотреть новый подход. Я не вкладываю много средств в наборы данных, но они соблазнительны с точки зрения ввода / вывода данных из вашей базы данных без написания большого количества кода. Это «соединительная» часть с элементами управления, которая, кажется, исчезает в сорняках. Что ж, я думаю, мне пора искать «строго типизированную объектную модель» и «INotifyPropertyChanged».