/// <summary> /// This is called when a bound control on the new row changes /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> /// <remarks>When a bound control on the new row changes, we can turn off the <see cref="IsNewRowInternal"/> /// flag so that the row will be committed when it loses the focus.</remarks> private void Target_PropertyChanged(object sender, EventArgs e) { // Occasionally, this gets called again after we've already seen it and added the row. Ignore those // calls. if (!this.IsNewRowInternal) { return; } // See if the user wants to allow the addition DataListCancelEventArgs ce = new DataListCancelEventArgs(-1, null); this.TemplateParent.OnAddingRow(ce); if (ce.Cancel) { this.CancelChanges(); } else { this.IsNewRowInternal = false; this.WirePropChangedEvents(false); this.TemplateParent.AddNewRowTemplate(); // Tell the user the new row has been added this.TemplateParent.OnAddedRow(new DataListEventArgs(this.TemplateParent.CurrentRow, this)); } }
/// <summary> /// Prevent phone information from being entered if the parent row doesn't yet exist in the related data /// source or is not valid. /// </summary> /// <param name="s">The sender of the event</param> /// <param name="e">The event arguments</param> private void dlPhones_AddingRow(object sender, DataListCancelEventArgs e) { DataRowView drv = (DataRowView)dnNav.ListManager.List[dnNav.CurrentRow]; if(drv.IsNew) { // The add must always be canceled e.Cancel = true; // If not valid, go back to the panel. If valid, we need to rebind or the related data source // doesn't always pick up on the fact that the parent row got added. if(!dnNav.IsValid) txtLName.Focus(); else dlPhones.SetDataBinding(dsAddresses, "Addresses.AddrPhone", typeof(PhoneRow)); } }
/// <summary> /// This is called when a bound control on the new row changes /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> /// <remarks>When a bound control on the new row changes, we can turn off the <see cref="IsNewRowInternal"/> /// flag so that the row will be committed when it loses the focus.</remarks> private void Target_PropertyChanged(object sender, EventArgs e) { // Occasionally, this gets called again after we've already seen it and added the row. Ignore those // calls. if(!this.IsNewRowInternal) return; // See if the user wants to allow the addition DataListCancelEventArgs ce = new DataListCancelEventArgs(-1, null); this.TemplateParent.OnAddingRow(ce); if(ce.Cancel) this.CancelChanges(); else { this.IsNewRowInternal = false; this.WirePropChangedEvents(false); this.TemplateParent.AddNewRowTemplate(); // Tell the user the new row has been added this.TemplateParent.OnAddedRow(new DataListEventArgs(this.TemplateParent.CurrentRow, this)); } }
/// <summary> /// Handle the escape key press to cancel changes /// </summary> /// <returns>Always returns true</returns> private bool HandleEscapeKey() { TemplateControl tc; int row; tc = this.CurrentItem; if(tc != null && !tc.IsNewRowInternal) { // Row may not be the same afterwards if canceling changes on the new row row = currentRow; DataListCancelEventArgs ce = new DataListCancelEventArgs(row, tc); OnCancelingEdits(ce); if(!ce.Cancel) { this.CancelChanges(); // If the row changed, pass null and -1 to indicate that the old row went away if(currentRow != row) OnCanceledEdits(new DataListEventArgs(-1, null)); else OnCanceledEdits(new DataListEventArgs(row, tc)); } } return true; }
/// <summary> /// This is called to handle the actual deletion of rows when requested by the user and also when a row /// is deleted externally from the data source other than by us. /// </summary> /// <param name="delRow">The row to delete</param> /// <param name="externalRequest">True if the request didn't come from us, false if it was requested by /// us.</param> private bool DeleteRowInternal(int delRow, bool externalRequest) { Control c; ControlCollection cc; TemplateControl tc; int ctlRow; // Nested deletes are not supported if(inDelRow) return false; ctlRow = delRow; if(showSep) ctlRow *= 2; cc = pnlRows.Controls; tc = (TemplateControl)cc[ctlRow]; // Ignore the request if on the new row template if(tc.IsNewRowInternal) return false; // If someone besides us removed the row, remove the row template without asking if(!externalRequest) try { inDelRow = true; // See if the user will allow the delete to occur DataListCancelEventArgs ce = new DataListCancelEventArgs(delRow, tc); // Allow the row template a chance to allow or deny the deletion. It has the current row // values in its controls which may or may not be in the data source yet due to the way data // binding works. if(tc.CanDelete) OnDeletingRow(ce); else ce.Cancel = true; // Ignore the request if canceled if(ce.Cancel) { // Return focus to the row template to avoid some weird data binding issues if(!tc.ContainsFocus) tc.Focus(); return false; } // If deleting the current row, cancel any pending changes if(delRow == currentRow) this.CancelChanges(); } finally { inDelRow = false; } Cursor oldCursor = this.Cursor; if(oldCursor != Cursors.WaitCursor) this.Cursor = Cursors.WaitCursor; try { inDelRow = true; // Remove the row template and separator pnlRows.SuspendLayout(); cc.RemoveAt(ctlRow); tc.Dispose(); if(showSep) { c = cc[ctlRow]; cc.RemoveAt(ctlRow); c.Dispose(); } // Delete the row from the data source if it is there if(!externalRequest && delRow < listManager.Count) listManager.RemoveAt(delRow); // Adjust the row selection if necessary if(selStart != -1) if(delRow >= selStart && delRow <= selEnd) { selEnd--; if(selEnd < selStart) selStart = selEnd = -1; } else if(delRow < selStart) { selStart--; selEnd--; } // Adjust the position of the other controls and rebind them to their new row while(ctlRow < cc.Count) { c = cc[ctlRow]; c.Top -= rowHeight; tc = c as TemplateControl; if(tc != null && !tc.IsNewRowInternal) { tc.SetRowSourceInternal(listManager.List[delRow]); delRow++; } ctlRow++; } } finally { if(oldCursor != Cursors.WaitCursor) this.Cursor = oldCursor; inDelRow = false; pnlRows.ResumeLayout(); } lblRowCount.Text = LR.GetString("DLNavRowCount", listManager.Count); if(rowHeadersVisible) { this.Invalidate(new Rectangle(0, 0, rowHeaderWidth, this.Height), false); this.Update(); } // Force the focus to the proper row currentRow = -1; DataSource_PositionChanged(this, EventArgs.Empty); OnDeletedRow(new DataListEventArgs(-1, null)); // If there are no rows and additions are allowed, focus the new row template if(currentRow == -1 && changePolicy.AllowAdditions) this.RowTemplate_Enter(pnlRows.Controls[0], EventArgs.Empty); btnDelete.Enabled = (changePolicy.AllowDeletes && listManager.Count > 0); return true; }
/// <summary> /// This raises the <see cref="CancelingEdits"/> event /// </summary> /// <param name="e">The event arguments</param> protected internal virtual void OnCancelingEdits(DataListCancelEventArgs e) { var handler = CancelingEdits; if(handler != null) handler(this, e); }
/// <summary> /// This raises the <see cref="DeletingRow"/> event /// </summary> /// <param name="e">The event arguments</param> protected virtual void OnDeletingRow(DataListCancelEventArgs e) { var handler = DeletingRow; if(handler != null) handler(this, e); }
/// <summary> /// This raises the <see cref="AddingRow"/> event /// </summary> /// <param name="e">The event arguments</param> protected internal virtual void OnAddingRow(DataListCancelEventArgs e) { var handler = AddingRow; if(handler != null) handler(this, e); }