我有一个绑定到可观察集合的数据网格。 当用户按下“添加按钮”时,它会添加一个新行,我通过向observablecollection添加一个新元素来完成此操作。
我无法弄清楚如何使第一个单元格成为新添加的行,就像我们正在编辑一样。我正在使用MVVM模式。
有任何想法或建议吗?
答案 0 :(得分:2)
The answer given by Gauss是正确的方法,但有了一些代码,它就更清晰了:
void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Loaded += Row_Loaded;
}
void Row_Loaded(object sender, RoutedEventArgs e)
{
var row = (DataGridRow) sender;
row.Loaded -= Row_Loaded;
DataGridCell cell = GetCell(dataGrid, row, 0);
if (cell != null) cell.Focus();
dataGrid.BeginEdit();
}
static DataGridCell GetCell(DataGrid dataGrid, DataGridRow row, int column)
{
if (dataGrid == null) throw new ArgumentNullException("dataGrid");
if (row == null) throw new ArgumentNullException("row");
if (column < 0) throw new ArgumentOutOfRangeException("column");
DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(row);
if (presenter == null)
{
row.ApplyTemplate();
presenter = FindVisualChild<DataGridCellsPresenter>(row);
}
if (presenter != null)
{
var cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
if (cell == null)
{
dataGrid.ScrollIntoView(row, dataGrid.Columns[column]);
cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
}
return cell;
}
return null;
}
static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
var visualChild = child as T;
if (visualChild != null)
return visualChild;
var childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
您检索DataGrid.LoadingRow
事件中的行,但该单元格尚不可用。因此,您在Loaded
事件上放置一个处理程序,以便等待此事件发生,然后您可以检索单元格并将焦点放在它上面。
删除处理程序以避免新的触发。
编辑会话也可以使用dataGrid.BeginEdit()
启动。
所有这些都在代码隐藏中,因为它属于视图。
答案 1 :(得分:1)
尝试捕获DataGrid的LoadingRow
(或类似)事件。在行上执行SetFocus(e.Row)
(或类似)。这纯粹是面向View的,所以它符合MVVM。
答案 2 :(得分:0)
你想做这样的事情:
DataGridCell cell = GetCell(rowIndex, colIndex);
cell.Focus;
当然,您需要难以捉摸的GetCell()方法。来自MSFT的Vincent Sibal在this forum post中写了这个方法(以及所需的GetRow)。当我遇到这个时,我正在寻找别的东西,所以我没有使用它,但其他人似乎已经好运了。您会注意到有his blog的链接,您可能会发现这些链接对DataGrid相关的所有内容都有帮助。
答案 3 :(得分:0)
希望能帮助他人。
我将在视图中显示MVVM方式:
<DataGrid Name="dg1" ItemsSource="{Binding Table}" AutoGenerateColumns="False" Margin="3" SelectionMode="Single" IsReadOnly="True" SelectedIndex="{Binding Path=SelectedIndex, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding mydate}" MinWidth="100"></DataGridTextColumn>
<DataGridTextColumn Header="Count" Binding="{Binding Count}" MinWidth="100"></DataGridTextColumn>
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" SourceName="dg1" >
<i:InvokeCommandAction Command="{Binding DgSelectionChanged}" CommandParameter="{Binding ElementName=dg1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
现在在View-Model中:
你需要在之后设置SelectedIndex:添加,删除等......和
private ICommand dgSelectionChanged;
/// <summary>
/// when the datagrid Selection Changes
/// </summary>
public ICommand DgSelectionChanged
{
get
{
return dgSelectionChanged ??
(dgSelectionChanged = new RelayCommand<DataGrid>(dg1 =>
{
// whatever you want when the Selection Changes
SelectedIndex= d
//select the item
if (dg1.SelectedIndex > -1)
{
dg1.Focus();
dg1.CurrentCell = new DataGridCellInfo(dg1.Items[dg1.SelectedIndex], dg1.Columns[0]);
}
}));
}
}
顺便说一下,要在加载控件后选择第一行,请将其添加到视图中:
<!-- select the row after control loaded -->
<i:EventTrigger EventName="Loaded" SourceName="dg1" >
<i:InvokeCommandAction Command="{Binding DgSelectionChanged}" CommandParameter="{Binding ElementName=dg1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
谢谢,Avi。
答案 4 :(得分:0)
对我有用的是LoadingRow
,e.Row.Loaded
和以下链接的GetCell()
方法的组合:
通过DataGrid.LoadingRow
在单元格可用之前调用GetCell
事件。但是在DaraGridRow.Loaded
事件中,单元格可用。
之后,您可以使用cell.Focus()
和DataGrid.BeginEdit()
。
答案 5 :(得分:0)
在我的案例中解决了这个问题,这要归功于杰克·伯格(Jake Berger)的回答。
绑定DataGrid的SelectedItem和处理LoadingRow事件的效果很好。
例如:
<DataGrid SelectionUnit="FullRow" SelectionMode="Single" ItemsSource="{Binding Source=MyList}" SelectedItem="{Binding SelectedDataItem, Mode=TwoWay}" LoadingRow="MyDataGrid_LoadingRow"></DataGrid>
private void MyDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
SelectedDataItem = (MyDataObject)e.Row.Item;
}