我有一個ObservableCollection綁定到DataGrid,我希望用戶能夠將數據添加到網格中,但只有在添加的所有條目總和小於100%。取消在DataGrid中添加新行
爲了讓數據網格聚焦接受數據的單元格,我使用了處理DataGrid.RowEditEnding事件的代碼。這是棘手的,但它的作品,一點。
我們有條目總計100%的地方。我可以在CollectionChanged事件處理程序中捕捉到我不想要的添加,但是當然我不能在那裏修改收集。
任何人都有一個建議,以獲得和處理不需要的添加的好地方?
乾杯,
Berryl
視圖模型的事件處理程序代碼
public ObservableCollection<RatioBagEntryVm> Ratios { get; private set; }
public RatioBagAllocatorVm() {
RatioBag = new RatioBag();
Ratios = new ObservableCollection<RatioBagEntryVm>();
Ratios.CollectionChanged += OnRatiosChanged;
}
private void OnRatiosChanged(object sender, NotifyCollectionChangedEventArgs e) {
SequencingService.Sequence(Ratios);
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var entryVm in e.NewItems.Cast<RatioBagEntryVm>()) {
entryVm.PropertyChanged += OnRatioEntryChanged;
RatioBag.Add(entryVm.Ratio);
entryVm.Bag = RatioBag;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (var entryVm in e.OldItems.Cast<RatioBagEntryVm>()) {
RatioBag.RemoveAt(entryVm.SequenceNumber - 1);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
碼處理程序的背後
/// <summary>
/// Adapted from http://blogs.msdn.com/b/vinsibal/archive/2009/04/14/5-more-random-gotchas-with-the-wpf-datagrid.aspx
/// </summary>
private void OnDataGridRowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
var dg = sender as DataGrid;
if (e.EditAction != DataGridEditAction.Commit) return;
//
// custom commit action:
// moves to the next row and opens the second cell for edit
// if the next row is the NewItemPlaceholder
//
var wasLastRowInGrid = e.Row.Item == dg.Items[dg.Items.Count - 2];
if (!wasLastRowInGrid) return;
if (dg.HasError()) return;
// set the new cell to be the last row and the second column
const int colIndex = 1;
var rowToSelect = dg.Items[dg.Items.Count - 1];
var colToSelect = dg.Columns[colIndex];
var rowIndex = dg.Items.IndexOf(rowToSelect);
switch (dg.SelectionUnit)
{
case DataGridSelectionUnit.Cell:
case DataGridSelectionUnit.CellOrRowHeader:
// select the new cell
dg.SelectedCells.Clear();
dg.SelectedCells.Add(new DataGridCellInfo(rowToSelect, colToSelect));
break;
case DataGridSelectionUnit.FullRow:
e.Row.IsSelected = true;
break;
default:
throw new ArgumentOutOfRangeException();
}
// this is the extra tricky part
Dispatcher.BeginInvoke(new DispatcherOperationCallback(param =>
{
// get the new cell, set focus, then open for edit
var cell = dg.GetCell(rowIndex, colIndex);
cell.Focus();
dg.BeginEdit();
return null;
}), DispatcherPriority.Background, new object[] { null });
}
}
SOLUTION(現在)
的原代碼的最棘手的部分正在使用Dispatcher模仿wh在你希望在DataGrid.RowEndedEvent中有可用時,按照Vincent Sibal編寫idea我基於我的代碼。
所以,這也是取消的地方,修改後的代碼如下。以這種方式訪問視圖模型幾乎不是MVVM摘要中的東西,當然也是黑客攻擊的手段,但是......它的工作原理。
// this is the extra tricky part
Dispatcher.BeginInvoke(new DispatcherOperationCallback(param =>
{
// get the new cell, set focus, then open for edit
var cell = dg.GetCell(rowIndex, colIndex);
cell.Focus();
// cancel the row commit if we are already fully allocated
var win = dg.FindVisualParent<Window>();
var vm = win.DataContext as RatioBagAllocatorVm;
if(vm.RatioBag.IsAllocatable)
e.Cancel = true;
else {
dg.BeginEdit();
}
return null;
}), DispatcherPriority.Background, new object[] { null });
@ianscol。是的,我寧願阻止添加,但不知道我可以在哪裏做到這一點! DataGrid觸發它... – Berryl 2012-03-02 19:18:47
你可以在'OnDataGridRowEditEnding'中設置'DataGridRowEditEndingEventArgs.Cancel = true'嗎?只要您可以設置事件,以便您可以訪問該事件中的比率,以便計算新的比率,那麼應使用「Cancel = true」來回滾該行。在我吐出上面的代碼之前,我應該首先想到這一點! – ianschol 2012-03-02 19:39:27
對接醜陋,但比屁股醜陋,不起作用!查看修改過的帖子結尾,瞭解我所做的事情。乾杯 – Berryl 2012-03-02 21:33:29