我有一个包含3列的DataGrid。
当用户在DataGrid的最后一个单元格上点击 Enter 时,我想向DataGrid添加一个新行。我已经使用DataGrid.InputBindings
成功完成了所有操作,但问题是当我在第二列上按 Enter 键时,会添加一个新行。我希望在焦点位于属于第3列的单元格时添加,然后按Enter键。
这是我的代码:
<DataGrid CanUserAddRows="False" CanUserDeleteRows="True" CanUserReorderColumns="False" CanUserResizeColumns="False" AutoGenerateColumns="False"
ItemsSource="{Binding People}" SelectedItem="{Binding SelectedRow}" CurrentCell="{Binding SelectedCell, Mode=OneWayToSource}"
DataGridCell.GotFocus="DataGrid_CellGotFocus" SelectionMode="Single">
<DataGrid.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</DataGrid.InputBindings>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Confirmation" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding DataContext.SelectedConfirmation, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Visibility="{Binding DataContext.ConfirmationVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource boolToVisibilityConverter}}">
<ComboBox.Items>
<sys:String>Add New</sys:String>
<sys:String>End Of List</sys:String>
</ComboBox.Items>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Age" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
在视图模型中:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
People = new ObservableCollection<Person>();
People.Add(new Person());
NewRowCommand = new RelayCommand(NewRow);
}
private ObservableCollection<Person> _people;
public ObservableCollection<Person> People
{
get
{
return _people;
}
set
{
_people = value;
OnPropertyChanged("People");
}
}
private Person _selectedRow;
public Person SelectedRow
{
get
{
return _selectedRow;
}
set
{
_selectedRow = value;
OnPropertyChanged("SelectedRow");
if (_selectedRow == People.Last())
{
ConfirmationVisibility = true;
}
else
{
ConfirmationVisibility = false;
}
}
}
private bool _confirmationVisibility;
public bool ConfirmationVisibility
{
get
{
return _confirmationVisibility;
}
set
{
_confirmationVisibility = value;
OnPropertyChanged("ConfirmationVisibility");
}
}
private string _selectedConfirmation;
public string SelectedConfirmation
{
get
{
return _selectedConfirmation;
}
set
{
_selectedConfirmation = value;
OnPropertyChanged("SelectedConfirmation");
}
}
private DataGridCellInfo _selectedCell;
public DataGridCellInfo SelectedCell
{
get
{
return _selectedCell;
}
set
{
_selectedCell = value;
OnPropertyChanged("SelectedCell");
}
}
public ICommand NewRowCommand { get; set; }
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (SelectedCell.Column.Header.ToString() == "Age")
{
People.Add(new Person());
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
以下是在VS2012中创建的示例项目:https://drive.google.com/file/d/0B5WyqSALui0bWVNHcVFXU1hOQ00/edit?usp=sharing
答案 0 :(得分:2)
任何UIElement
都可以InputBindings
,而不只是DataGrid
。所以为什么不搬家
<DataGrid.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</DataGrid.InputBindings>
到您想要的列:
<DataGridTemplateColumn Header="Age" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}">
<TextBlock.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</TextBox.InputBindings>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
答案 1 :(得分:2)
当您按Enter键时,它会立即进入第3列而不是在您选择标题时创建列==年龄在等于确认时创建它。
这是您修改的工作代码,用于修复错误
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (SelectedCell.Column.Header.ToString() == "Confirmation")
{
People.Add(new Person());
}
}
}
}
只需执行此操作,当用户按下最后一列时,您的示例将使用新行创建 希望你的问题得到解决,并为自己赢得了第一个答案和积分。
答案 2 :(得分:2)
代码的问题在于CurrentCell属性绑定。 它在调用NewRowCommand之前绑定新的当前单元格。
让我们假设你在哪里&#34;姓名&#34;最后一行的列,所以会发生什么:
我建议在currentcell更新时保留对前一个单元格的引用。并使用它而不是currentCell。
public DataGridCellInfo SelectedCell
{
get
{
return _selectedCell;
}
set
{
_lastCell = _selectedCell; //here is my edit
_selectedCell = value;
OnPropertyChanged("SelectedCell");
}
}
所以新的NewRow(对象obj)看起来像这样:
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (_lastCell.Column !=null && _lastCell.Column.Header.ToString() =="Age")//here is my edit
{
People.Add(new Person());
}
}
}
}
DataGrid_CellGotFocus(对象发送者,RoutedEventArgs e)中也存在问题。看看我的编辑,我放弃了行。我选择了分配。
private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e)
{
// Lookup for the source to be DataGridCell
if (e.OriginalSource.GetType() == typeof(DataGridCell))
{
// Starts the Edit on the row;
DataGrid grd = (DataGrid)sender;
grd.BeginEdit(e);
Control control = GetFirstChildByType<Control>(e.OriginalSource as DataGridCell);
if (control != null)
{
control.Focus();
}
DataGridCell cell = GetDataGridCell(grd.CurrentCell);
DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
if (dataGrid != null)
{
if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
if (!cell.IsSelected)
cell.IsSelected = true;
}
}
}
}
我在电脑上运行了编辑过的代码,效果很好!如果我可能错过任何问题,请告诉我。