里面的Delete不起作用,下面想用源码来解释这一现象,理解为什么删除不起作用:
当我点击次Delete时,在服务器端经历了以下步骤来处理:
this.RaisePostBackEvent(this._requestValueCollection);(Page 类里的ProcessRequest的一行)_requestValueCollection 为NameValueCollection 类
------
private void RaisePostBackEvent(NameValueCollection postData)
{
if (this._registeredControlThatRequireRaiseEvent != null)
{
this.RaisePostBackEvent(this._registeredControlThatRequireRaiseEvent, null);
}
else
{
string str = postData["__EVENTTARGET"];
bool flag = !string.IsNullOrEmpty(str);
if (flag || (this.AutoPostBackControl != null))//此时AutoPostBack不为空
{
Control control = null;
if (flag)
{
control = this.FindControl(str);//最后找到GridView控件
}
if ((control != null) && (control.PostBackEventHandler != null))
{
string eventArgument = postData["__EVENTARGUMENT"];
this.RaisePostBackEvent(control.PostBackEventHandler, eventArgument);//单步进入此行,由于GridView实现了IPostBackEventHandler接口,所以可以在此处被传入,此时eventArguent 为:"Delete$0"
}
}
else
{
this.Validate();
}
}
}
------------------------------
以下调用:
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
sourceControl.RaisePostBackEvent(eventArgument);
}
----------------------------------
进入GridView的RaisePostBackEvent 方法 :
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
this.RaisePostBackEvent(eventArgument);
}
protected virtual void RaisePostBackEvent(string eventArgument) {
base.ValidateEvent(this.UniqueID, eventArgument);
int index = eventArgument.IndexOf('$');
if (index >= 0)
{
CommandEventArgs originalArgs = new CommandEventArgs(eventArgument.Substring(0, index), eventArgument.Substring(index + 1));
GridViewCommandEventArgs e = new GridViewCommandEventArgs(null, this, originalArgs);
this.HandleEvent(e, false, string.Empty);//根据e的值来做不同的处理,此时的e为:
}
}
下面会进入核心的 处理方法 :
private bool HandleEvent(EventArgs e, bool causesValidation, string validationGroup)
{
bool flag = false;
this.ResetModelValidationGroup(causesValidation, validationGroup);
GridViewCommandEventArgs args = e as GridViewCommandEventArgs;
if (args == null)
{
return flag;
}
this.OnRowCommand(args);
flag = true;
string commandName = args.CommandName;
if (StringUtil.EqualsIgnoreCase(commandName, "Select"))
{
this.HandleSelect(this.GetRowIndex(args.Row, (string) args.CommandArgument));
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Page"))
{
string commandArgument = (string) args.CommandArgument;
int pageIndex = this.PageIndex;
if (StringUtil.EqualsIgnoreCase(commandArgument, "Next"))
{
pageIndex++;
}
else if (StringUtil.EqualsIgnoreCase(commandArgument, "Prev"))
{
pageIndex--;
}
else if (StringUtil.EqualsIgnoreCase(commandArgument, "First"))
{
pageIndex = 0;
}
else if (StringUtil.EqualsIgnoreCase(commandArgument, "Last"))
{
pageIndex = this.PageCount - 1;
}
else
{
pageIndex = Convert.ToInt32(commandArgument, CultureInfo.InvariantCulture) - 1;
}
this.HandlePage(pageIndex);
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Sort"))
{
this.HandleSort((string) args.CommandArgument);
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Edit"))
{
this.HandleEdit(this.GetRowIndex(args.Row, (string) args.CommandArgument));
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Update"))
{
this.HandleUpdate(args.Row, this.GetRowIndex(args.Row, (string) args.CommandArgument), causesValidation);
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Cancel"))
{
this.HandleCancel(this.GetRowIndex(args.Row, (string) args.CommandArgument));
return flag;
}
if (StringUtil.EqualsIgnoreCase(commandName, "Delete"))
{
this.HandleDelete(args.Row, this.GetRowIndex(args.Row, (string) args.CommandArgument));//由于 传入丢的参数为Delete所以会在此出进入.
return flag;
}
return this.HandleCommand(args.Row, this.GetRowIndex(args.Row, (string) args.CommandArgument), commandName);
}
---------------------------------
根据传递的参数来进入 以下HandleDelete方法来处理:
private void HandleDelete(GridViewRow row, int rowIndex)
{
DataSourceView data = null;
bool isBoundUsingDataSourceID = base.IsBoundUsingDataSourceID;
//此处就是ObjectDataSource被绑定后,GridView的方法就可以调用ObjectDataSource提供的方法
if (isBoundUsingDataSourceID)
{
data = this.GetData();此时的this就是:GridView,其基类:
//从ObjectDataSource获得绑定的方法得到数据,由于是使用的Delete所以不明白为何得到数据,所以以下会再做分析,是如何Delete更新会数据库的,并分析他的存在意义.
if (data == null)//显然得到了数据,类型为:System.Web.UI.WebControls.ObjectDataSourceView
{
throw new HttpException(System.Web.SR.GetString("GridView_DataSourceReturnedNullView", new object[] { this.ID }));
}
}
if ((row == null) && (rowIndex < this.Rows.Count))
{
row = this.Rows[rowIndex];
}
GridViewDeleteEventArgs e = new GridViewDeleteEventArgs(rowIndex);
if (row != null)
{
this.ExtractRowValues(e.Values, row, true, false);
}
if (this.DataKeys.Count > rowIndex)
{
foreach (DictionaryEntry entry in this.DataKeys[rowIndex].Values)
{
e.Keys.Add(entry.Key, entry.Value);
if (e.Values.Contains(entry.Key))
{
e.Values.Remove(entry.Key);
}
}
}
this.OnRowDeleting(e);//此行应该是把删除的操作发送给客户端
if (!e.Cancel)
{
this._deletedRowIndex = rowIndex;
if (isBoundUsingDataSourceID)
{
this._deleteKeys = e.Keys;
this._deleteValues = e.Values;
data.Delete(e.Keys, e.Values, new DataSourceViewOperationCallback(this.HandleDeleteCallback));//此行的功能应该是把删除的数据更新回数据库的过程. }
}
}
--------____________________
先分析:Data.Delete 方法:原型如下:
public virtual void Delete(IDictionary keys, IDictionary oldValues, DataSourceViewOperationCallback callback)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
int affectedRecords = 0;
bool flag = false;
try
{
affectedRecords = this.ExecuteDelete(keys, oldValues);//后面调试发现,ObjectDataSource通过反射调用的
}
catch (Exception ex)
{
flag = true;
if (!callback(affectedRecords, ex))
{
throw;
}
}
finally
{
if (!flag)
{
callback(affectedRecords, null);
}
}
}
在 affectedRecords = this.ExecuteDelete(keys, oldValues);此处单步进入后:
通过反射调用方法,如何传递参数呢?
下面暂停一下,研究一小会儿反射,十分钟后.....
反射 的参数是在method的变量Parameter中 传入的,以键值对的形式传入,由于没有设置DataKeyNames属性,传入的值始终为空,(有一个有趣的现象 是,当传入的值为空时,执行反射的方法会发现整型的参数的变量为零?
)
其实在GridView1的DataKeyNames 中添加属性:UserId,即可.具体为什么要这么用,它和上面分析的Parameters有什么关系?下面分析源代码来理解:
DataKeyNames的定义如下:
public virtual string[] DataKeyNames
{
get
{
object obj2 = this._dataKeyNames;
if (obj2 != null)
{
return (string[]) ((string[]) obj2).Clone();
}
return new string[0];
}
set
{
if (!DataBoundControlHelper.CompareStringArrays(value, this.DataKeyNamesInternal))
{
if (value != null)
{
this._dataKeyNames = (string[]) value.Clone();
}
else
{
this._dataKeyNames = null;
}
this.ClearDataKeys();
if (base.Initialized)
{
base.RequiresDataBinding = true;
}
}
}
}
其实就是简单封装一下,没有啥关键性的东西.在这里 暂停一下,
看一下以上method的参数其实是由一个字典来赋值 的,其关键的 代码如下:
MergeDictionaries(this.DeleteParameters, this.DeleteParameters.GetValues(this._context, this._owner), dictionary2);
总结如下,this.DeleteParameters 此参数被赋值是由于在开始设置了DataKeyNames属性.但是DataKeyNames是在什么时候被赋值的?,先暂时研究到这里.