Поэтому я использую WPF и шаблон MVVM. У меня есть свойство ItemSource моей сетки данных, привязанное к коллекции объектов домена в моей ViewModel. В сетке данных также определен RowDetailsTemplate, который помогает мне изменять все мои свойства в моем объекте домена. У меня настроена сетка данных, поэтому она позволяет выбирать только одну строку за раз.
Если вам интересно, вот как выглядит мое объявление datagrid:
<DataGrid Name="detailsDataGrid" Grid.Row="1"
AutoGenerateColumns="False"
ItemsSource="{Binding Source={StaticResource Locator}, Path=Details.FileMoverDetails, Mode=OneWay, ValidatesOnDataErrors=True}"
SelectedItem="{Binding Source={StaticResource Locator}, Path=Details.SelectedDetail, Mode=TwoWay, ValidatesOnDataErrors=True}"
AreRowDetailsFrozen="True" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" SelectionMode="Single">
Таким образом, вы также заметите, что SelectedItem также привязан к свойству в моей ViewModel.
Вот моя проблема: под моей сеткой данных у меня есть кнопка «добавить новую запись».
<Button Name="newRecordBtn" DockPanel.Dock="Right" Margin="0,0,10,0" Click="newRecordBtn_Click" >New Record</Button>
который (внутри события щелчка) выполняет мою «AddDetailCommand» в моей ViewModel. «AddDetailCommand» просто создает новый объект домена, добавляет его в коллекцию объектов домена ViewModel, а затем устанавливает свойство ViewModel «SelectedDetail» для вновь созданного объекта. Затем я вызываю RaisePropertyChanged("FileMoverDetails"), за которым следует RaisePropertyChanged("SelectedDetail").
Это заставляет мою сетку данных выбирать вновь созданный элемент и расширять сведения о строке сетки данных. В сведениях о строке моей сетки данных есть много полей, включая поля со списком и текстовые поля. Что подводит меня к моей реальной проблеме: когда я щелкаю левой кнопкой мыши один раз в одном из моих текстовых полей, чтобы начать печатать, фокус не помещается в текстовое поле, и я нужно щелкнуть второй раз, прежде чем я смогу начать печатать. Это происходит с любым элементом управления внутри моих сведений о строке: мне нужно щелкнуть один раз по любому элементу управления, а затем щелкнуть второй раз, прежде чем что-либо произойдет. Эта проблема возникает только в том случае, если я нажимаю кнопку «Добавить новую запись». Это означает, что если я выберу уже существующую строку в сетке данных, то фокус будет правильным, и я могу щелкнуть один раз на любом элементе управления сведениями о строке, и он будет работать так, как ожидалось.
В качестве другого примера проблемы, с которой я сталкиваюсь, у меня есть кнопка «удалить запись» в сведениях о строке сетки данных, которая при активации удаляет текущий выбранный объект домена из коллекции элементов сетки данных. После нажатия кнопки «Добавить новую запись» я иду и сразу же нажимаю один раз кнопку «удалить запись», и ничего не происходит. Но когда я нажимаю второй раз, кнопка работает.
Так что я спрашиваю? После того, как я нажму кнопку "добавить новую запись", я хочу иметь возможность щелкнуть один раз кнопку "удалить запись" и активировать ее функции, не нажимая еще раз .
.
.
Дополнительная информация:
Я думал, что это была чисто проблема с фокусом, поэтому я изменил событие Click кнопки «Добавить новую запись», чтобы установить фокус на один из элементов управления TextBox с данными строки данных после добавления новой записи:
private void newRecordBtn_Click(object sender, RoutedEventArgs e)
{
if (e.Source == newRecordBtn)
{
ExecuteNewRecordButtonCommand();
e.Handled = true;
}
}
private void ExecuteNewRecordButtonCommand()
{
if (newRecordBtn.Command.CanExecute(null))
{
newRecordBtn.Command.Execute(null);
if (detailsDataGrid.Items.Count > 0)
{
detailsDataGrid.UpdateLayout();
DataGridRow selectedRow = (DataGridRow)(detailsDataGrid.ItemContainerGenerator.ContainerFromItem(detailsDataGrid.SelectedItem));
//Get the ContentPresenter of the row details.
DataGridDetailsPresenter presenter = FindVisualChild<DataGridDetailsPresenter>(selectedRow);
// Find the localDirectoryText TextBox
DataTemplate template = presenter.ContentTemplate;
System.Windows.Controls.TextBox localDirTxt = (System.Windows.Controls.TextBox)template.FindName("localDirectoryText", presenter);
localDirTxt.Focus();
}
}
}
Угадайте, что случилось? Он установил фокус клавиатуры в TextBox, как я и ожидал (я могу сразу начать печатать, и он поместит мой напечатанный текст в TextBox). Но когда я нажимаю один раз на другом текстовом поле, на кнопке "Удалить запись" или на другом элементе управления (все они находятся в деталях строк сетки данных), ничего не происходит! Затем мне нужно щелкнуть секунду, чтобы элемент управления сделал то, что я ожидал, только один щелчок.
Пожалуйста, помогите, я так старался заставить это работать, и это очень расстраивает. Даже если вы не можете помочь, я хочу поблагодарить вас за то, что вы добрались до этого места в этом описании, я знаю, что оно очень длинное.
Вот мой XAML View (ну, по крайней мере, соответствующие части, я удаляю вещи и помещаю "..." в места, где вещи были удалены):
<Grid>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<DataGrid Name="detailsDataGrid" Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource Locator}, Path=Details.FileMoverDetails, Mode=OneWay, ValidatesOnDataErrors=True}" SelectedItem="{Binding Source={StaticResource Locator}, Path=Details.SelectedDetail, Mode=TwoWay, ValidatesOnDataErrors=True}" AreRowDetailsFrozen="True" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" SelectionMode="Single">
<DataGrid.Columns>
...
<DataGridTextColumn Header="Local Directory" Binding="{Binding Path=LocalDirectory, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Width="175"/>
<DataGridTextColumn Header="Remote Directory" Binding="{Binding Path=RemoteDirectory, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Width="175"/>
...
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Grid Name="rowDetailsGrid" Margin="5,10,0,10" Width="{Binding ElementName=detailsView, Path=ActualWidth}" HorizontalAlignment="Left" VerticalAlignment="Top" DataContext="{Binding Source={StaticResource Locator}, Path=Details.SelectedDetail}" IsEnabled="{Binding Source={StaticResource Locator}, Path=Details.CanEditDetails, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="190"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="8" Grid.ColumnSpan="3" Orientation="Vertical">
...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Name="localDirectoryText" Text="{Binding Path=LocalDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" PreviewKeyDown="localDirectoryText_PreviewKeyDown"/>
<Button Grid.Column="1" Width="20" Margin="3,3,0,3" Name="localDirectoryButton" Click="localDirectoryButton_Click">...</Button>
</Grid>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="9" Grid.ColumnSpan="3" Orientation="Vertical">
...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Name="remoteDirectoryText" Text="{Binding Path=RemoteDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" PreviewKeyDown="remoteDirectoryText_PreviewKeyDown"/>
<Button Grid.Column="1" Width="20" Margin="3,3,0,3" Name="remoteDirectoryButton" Click="remoteDirectoryButton_Click">...</Button>
</Grid>
</StackPanel>
...
<DockPanel Grid.Column="4" Grid.Row="10" LastChildFill="False">
<Button Name="removeRecordBtn" DockPanel.Dock="Right" Margin="0,15,0,0" Command="{Binding Path=RemoveSelectedDetailCommand}">Remove Record</Button>
</DockPanel>
</Grid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
<Grid Grid.Row="2" DataContext="{Binding Source={StaticResource Locator}, Path=Details}" IsEnabled="{Binding Path=HasInstance, Mode=OneWay}" Width="{Binding ElementName=detailsView, Path=ActualWidth}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto" MinWidth="125"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="1" LastChildFill="False" Margin="0,10,0,7">
<Button Name="newRecordBtn" DockPanel.Dock="Right" Margin="0,0,10,0" Command="{Binding Path=AddDetailCommand}" Click="newRecordBtn_Click" >New Record</Button>
</DockPanel>
</Grid>
</Grid>