【发布时间】:2011-01-06 17:33:11
【问题描述】:
我正在使用 WPF DataGrid(.Net 3.5 SP 1 版本来自 Toolkit)
我可以订阅什么事件来检测何时添加了新行? (例如,当用户向下移动光标或按下 Enter 时,一个新的空白行被添加到网格中)。
最终我想做的是使用该事件来计算一些默认值并将它们放在新行中。
网格绑定到DataTable,如果这有什么不同的话。
【问题讨论】:
我正在使用 WPF DataGrid(.Net 3.5 SP 1 版本来自 Toolkit)
我可以订阅什么事件来检测何时添加了新行? (例如,当用户向下移动光标或按下 Enter 时,一个新的空白行被添加到网格中)。
最终我想做的是使用该事件来计算一些默认值并将它们放在新行中。
网格绑定到DataTable,如果这有什么不同的话。
【问题讨论】:
您要查找的事件是DataGrid.AddingNewItem event。此事件将允许您根据需要配置新对象,然后将其应用于AddingNewItemEventArgs 的NewItem 属性。
XAML:
<DataGrid Name="GrdBallPenetrations"
ItemsSource="{Binding BallPenetrationCollection}"
SelectedItem="{Binding CurrentSelectedBallPenetration}"
AutoGenerateColumns="False"
IsReadOnly="False"
CanUserAddRows="True"
CanUserDeleteRows="True"
IsSynchronizedWithCurrentItem="True"
AddingNewItem="GrdBallPenetrations_AddingNewItem">
C# 中的代码:
private void GrdBallPenetrations_AddingNewItem(object sender,
AddingNewItemEventArgs e)
{
e.NewItem = new BallPenetration
{
Id = Guid.NewGuid(),
CarriageWay = CariageWayType.Plus,
LaneNo = 1,
Position = Positions.BetweenWheelTracks
};
}
【讨论】:
ItemsSource 绑定添加的,则不会触发AddingNewItem 事件。
当用户离开他正在编辑的行时,对象会被持久化(插入或更新)。移动到同一行中的另一个单元格会通过数据绑定更新相应的属性,但尚未向模型(或数据访问层)发出信号。唯一有用的事件是 DataGrid.RowEditEnding。这是在提交修改的行之前触发的。
XAML
<DataGrid ...
RowEditEnding="MyDataGrid_RowEditEnding">
</DataGrid>
代码背后
private void MyDataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{ // Only act on Commit
if (e.EditAction == DataGridEditAction.Commit)
{
var newItem = e.Row.DataContext as MyDataboundType;
if (newItem is NOT in my bound collection) ... handle insertion...
}
}
此解决方案的所有功劳归于 Diederik Krolls (Original Post)。尊敬的。
【讨论】:
我建议不要在 View(网格)中处理事件,而是观看绑定的对象,并将逻辑放在那里。这使您的业务逻辑与您的业务对象保持一致。
由于您已绑定到DataTable,因此最简单的方法是订阅DataTable.TableNewRow。
【讨论】:
我添加这个是因为我刚刚花了将近 2 个小时试图弄清楚如何让 DataGrid 添加一个新行,当您绑定到一组视图模型并且您需要控制那些视图模型。
所以设置是你有一个ObservableCollection<MyViewModel> 绑定到你的DataGrid 的ItemsSource。你需要在视图模型层自己创建MyViewModel。
这是 DataGrid 在自动添加行时的运行方式:
MyViewModel 的新实例,它将通过调用该类型的默认构造函数来绑定到该行。谁知道它为什么这样做,但如果MyViewModel 没有默认构造函数,它将无法显示该空白行。这可能是您卡住的地方,因为您没有默认构造函数,因为您需要自己创建对象。 不幸的是,你需要去添加一个。再次注意,如果元素类型是一个接口,这注定会失败。集合的元素类型必须是具有默认构造函数的具体类。AddingNewItem:您可以在此处拦截添加操作并切换默认构造函数创建的实例,它使用您自己的实例创建。 AddingNewItemEventArgs.NewItem 有一个设置器,您可以将当前项目换成自己的。【讨论】:
我发现 DataGrid_InitializingNewItem 事件很有帮助,您可以在其中检查 e.NewItem 并根据其类型采取适当的措施。
【讨论】:
与AddingNewItem 不同,DataGrid.LoadingRow Event(从 .Net 4.0 开始可用)将为通过ItemSource 绑定添加的项目触发。
【讨论】:
在您的 XAML 中,在您的 Window 标记中包含以下代码:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"
接下来,在 DataGrid 元素中,添加以下触发器:
<DataGrid ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="LoadingRow">
<cmd:EventToCommand Command="{Binding LoadRowHandler}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
接下来,在您的 View Model 中,添加一个用于处理事件的命令:
public RelayCommand<DataGridRowEventArgs> LoadRowHandler{ get; private set; }
在构造函数内部,初始化命令:
LoadRowHandler = new RelayCommand<DataGridRowEventArgs>(LoadingRowHandlerMethod);
接下来,创建一个要放置逻辑的方法:
private void LoadingRowHandlerMethod(DataGridRowEventArgs e)
{
//....
//....
}
就是这样。现在,每当向 DataGrid 添加新行时,都会执行 LoadingRowHandlerMethod。
希望对你有帮助。
【讨论】: