随笔 - 547  文章 - 213 评论 - 417 阅读 - 107万

先从OnItemUpdating和OnItemUpdated事件开始:

        protected virtual void OnItemUpdating(DetailsViewUpdateEventArgs e)
        {
            
bool flag1 = base.IsBoundUsingDataSourceID;
            DetailsViewUpdateEventHandler handler1 
= (DetailsViewUpdateEventHandler) base.Events[DetailsView.EventItemUpdating];
            
if (handler1 != null)
            {
                handler1(
this, e);
            }
            
else if (!flag1 && !e.Cancel)
            {
                
throw new HttpException(System.Web.SR.GetString("DetailsView_UnhandledEvent"new object[] { this.ID, "ItemUpdating" }));
            }
        }

        protected virtual void OnItemUpdated(DetailsViewUpdatedEventArgs e)
        {
            DetailsViewUpdatedEventHandler handler1 
= (DetailsViewUpdatedEventHandler) base.Events[DetailsView.EventItemUpdated];
            
if (handler1 != null)
            {
                handler1(
this, e);
            }
        }

从这两个方法中看不出什么,只是一个简单的事件触发函数。下面看看它们被调用的地方:
1.  OnItemUpdating方法被HandleUpdate方法调用:

        private void HandleUpdate(string commandArg, bool causesValidation)
        {
            
if ((!causesValidation || (this.Page == null)) || this.Page.IsValid)
            {
                
if (this.Mode != DetailsViewMode.Edit)
                {
                    
throw new HttpException(System.Web.SR.GetString("DetailsViewFormView_ControlMustBeInEditMode"new object[] { "DetailsView"this.ID }));
                }
                
if (this.PageIndex >= 0)
                {
                    DataSourceView view1 
= null;
                    
bool flag1 = base.IsBoundUsingDataSourceID;
                    
if (flag1)
                    {
                        view1 
= this.GetData();
                        
if (view1 == null)
                        {
                            
throw new HttpException(System.Web.SR.GetString("View_DataSourceReturnedNullView"new object[] { this.ID }));
                        }
                    }
                    DetailsViewUpdateEventArgs args1 
= new DetailsViewUpdateEventArgs(commandArg);
                    
if (flag1)
                    {
                        
foreach (DictionaryEntry entry1 in this.BoundFieldValues)
                        {
                            args1.OldValues.Add(entry1.Key, entry1.Value);
                        }
                        
this.ExtractRowValues(args1.NewValues, falsetrue);
                        
foreach (DictionaryEntry entry2 in this.DataKey.Values)
                        {
                            args1.Keys.Add(entry2.Key, entry2.Value);
                        }
                    }
                    
this.OnItemUpdating(args1);
                    
if (!args1.Cancel && flag1)
                    {
                        
this._updateKeys = args1.Keys;
                        
this._updateNewValues = args1.NewValues;
                        
this._updateOldValues = args1.OldValues;
                        view1.Update(args1.Keys, args1.NewValues, args1.OldValues, 
new DataSourceViewOperationCallback(this.HandleUpdateCallback));
                    }
                }
            }
        }

2. OnItemUpdated方法被HandleUpdateCallback调用
        private bool HandleUpdateCallback(int affectedRows, Exception ex)
        {
            DetailsViewUpdatedEventArgs args1 
= new DetailsViewUpdatedEventArgs(affectedRows, ex);
            args1.SetOldValues(
this._updateOldValues);
            args1.SetNewValues(
this._updateNewValues);
            args1.SetKeys(
this._updateKeys);
            
this.OnItemUpdated(args1);
            
this._updateKeys = null;
            
this._updateOldValues = null;
            
this._updateNewValues = null;
            
if ((ex != null&& !args1.ExceptionHandled)
            {
                
return false;
            }
            
if (!args1.KeepInEditMode)
            {
                DetailsViewModeEventArgs args2 
= new DetailsViewModeEventArgs(this.DefaultMode, false);
                
this.OnModeChanging(args2);
                
if (!args2.Cancel)
                {
                    
this.Mode = args2.NewMode;
                    
this.OnModeChanged(EventArgs.Empty);
                    
base.RequiresDataBinding = true;
                }
            }
            
return true;
        }

下面看看HandleUpdate,HandleUpdateCallback这两个方法被调用的地方:

1. HandleUpdate方法被调用的地方

        private bool HandleEvent(EventArgs e, bool causesValidation, string validationGroup)
        {
            
bool flag1 = false;
            
if (causesValidation && (this.Page != null))
            {
                
this.Page.Validate(validationGroup);
            }
            DetailsViewCommandEventArgs args1 
= e as DetailsViewCommandEventArgs;
            
if (args1 != null)
            {
                
this.OnItemCommand(args1);
                flag1 
= true;
                
string text1 = args1.CommandName;
                
int num1 = this.PageIndex;
                
if (StringUtil.EqualsIgnoreCase(text1, "Page"))
                {
                    
string text2 = (string) args1.CommandArgument;
                    
if (StringUtil.EqualsIgnoreCase(text2, "Next"))
                    {
                        num1
++;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "Prev"))
                    {
                        num1
--;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "First"))
                    {
                        num1 
= 0;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "Last"))
                    {
                        
if (base.IsViewStateEnabled)
                        {
                            num1 
= this.PageCount - 1;
                        }
                        
else
                        {
                            num1 
= 0x7fffffff;
                        }
                    }
                    
else
                    {
                        num1 
= Convert.ToInt32(text2, CultureInfo.InvariantCulture) - 1;
                    }
                    
this.HandlePage(num1);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Edit"))
                {
                    
this.HandleEdit();
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Update"))
                {
                    
this.HandleUpdate((string) args1.CommandArgument, causesValidation);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Cancel"))
                {
                    
this.HandleCancel();
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Delete"))
                {
                    
this.HandleDelete((string) args1.CommandArgument);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Insert"))
                {
                    
this.HandleInsert((string) args1.CommandArgument, causesValidation);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "New"))
                {
                    
this.HandleNew();
                }
            }
            
return flag1;
        }

        public virtual void UpdateItem(bool causesValidation)
        {
            
this.HandleUpdate(string.Empty, causesValidation);
        }

2. HandleUpdateCallback方法被调用的地方

        private void HandleUpdate(string commandArg, bool causesValidation)
        {
            
if ((!causesValidation || (this.Page == null)) || this.Page.IsValid)
            {
                
if (this.Mode != DetailsViewMode.Edit)
                {
                    
throw new HttpException(System.Web.SR.GetString("DetailsViewFormView_ControlMustBeInEditMode"new object[] { "DetailsView"this.ID }));
                }
                
if (this.PageIndex >= 0)
                {
                    DataSourceView view1 
= null;
                    
bool flag1 = base.IsBoundUsingDataSourceID;
                    
if (flag1)
                    {
                        view1 
= this.GetData();
                        
if (view1 == null)
                        {
                            
throw new HttpException(System.Web.SR.GetString("View_DataSourceReturnedNullView"new object[] { this.ID }));
                        }
                    }
                    DetailsViewUpdateEventArgs args1 
= new DetailsViewUpdateEventArgs(commandArg);
                    
if (flag1)
                    {
                        
foreach (DictionaryEntry entry1 in this.BoundFieldValues)
                        {
                            args1.OldValues.Add(entry1.Key, entry1.Value);
                        }
                        
this.ExtractRowValues(args1.NewValues, falsetrue);
                        
foreach (DictionaryEntry entry2 in this.DataKey.Values)
                        {
                            args1.Keys.Add(entry2.Key, entry2.Value);
                        }
                    }
                    
this.OnItemUpdating(args1);
                    
if (!args1.Cancel && flag1)
                    {
                        
this._updateKeys = args1.Keys;
                        
this._updateNewValues = args1.NewValues;
                        
this._updateOldValues = args1.OldValues;
                        view1.Update(args1.Keys, args1.NewValues, args1.OldValues, 
new DataSourceViewOperationCallback(this.HandleUpdateCallback));
                    }
                }
            }
        }

从上面可以看到:
          HandleUpdateCallback 被 HandleUpdate 方法调用。
          HandleUpdate 被 HandleEvent 和 UpdateItem 方法调用。
现在看一下 HandleEvent 和 UpdateItem  方法调用:
1. HandleEvent方法被调用的地方:

        protected override bool OnBubbleEvent(object source, EventArgs e)
        {
            
bool flag1 = false;
            
string text1 = string.Empty;
            DetailsViewCommandEventArgs args1 
= e as DetailsViewCommandEventArgs;
            
if (args1 != null)
            {
                IButtonControl control1 
= args1.CommandSource as IButtonControl;
                
if (control1 != null)
                {
                    flag1 
= control1.CausesValidation;
                    text1 
= control1.ValidationGroup;
                }
            }
            
return this.HandleEvent(e, flag1, text1);
        }

        protected virtual void RaisePostBackEvent(string eventArgument)
        {
            
base.ValidateEvent(this.UniqueID, eventArgument);
            
int num1 = eventArgument.IndexOf('$');
            
if (num1 >= 0)
            {
                CommandEventArgs args1 
= new CommandEventArgs(eventArgument.Substring(0, num1), eventArgument.Substring(num1 + 1));
                DetailsViewCommandEventArgs args2 
= new DetailsViewCommandEventArgs(this, args1);
                
this.HandleEvent(args2, falsestring.Empty);
            }
        }

2. UpdateItem  方法是个虚方法,未找到被调用的地方,不过可以直接调用DetailsView.UpdateItem()方法。

下面研究RaisePostBackEvent被调用的地方:

        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
        {
            
this.RaisePostBackEvent(eventArgument);
        }

这里的IPostBackEventHandler是DetailsView继承的接口之一。

最后集中研究OnBubbleEvent和IPostBackEventHandler.RaisePostBackEvent方法被调用的地方,这里要涉及到页面的生命周期:

DetailsView.OnBubbleEvent 方法:

确定 Web 服务器控件的事件是否沿页的用户界面 (UI) 服务器控件层次结构向上传递。 

命名空间:System.Web.UI.WebControls
程序集:System.Web(在 system.web.dll 中)

语法
Visual Basic(声明) 
Protected Overrides Function OnBubbleEvent ( _
    source As Object, _
    e As EventArgs _
) As Boolean
 
Visual Basic(用法) 
Dim source As Object
Dim e As EventArgs
Dim returnValue As Boolean

returnValue 
= Me.OnBubbleEvent(source, e)
 
C# 
protected override bool OnBubbleEvent (
    Object source,
    EventArgs e
)
 
C
++ 
protected:
virtual bool OnBubbleEvent (
    Object
^ source, 
    EventArgs
^ e
override
 
J# 
protected boolean OnBubbleEvent (
    Object source, 
    EventArgs e
)
 
JScript 
protected override function OnBubbleEvent (
    source : Object, 
    e : EventArgs
) : boolean
 


参数
source
事件源。

e
包含事件数据的 EventArgs。



返回值
如果事件已被取消,则为 
true;否则为 false。 
备注
OnBubbleEvent 方法实现了 Control.OnBubbleEvent 方法以将事件从子控件传递到页层次结构。

给继承者的说明 在派生类中重写 OnBubbleEvent 时,一定要调用基类的 OnBubbleEvent 方法,以便已注册的委托对事件进行接收

Control.OnBubbleEvent 方法:

确定服务器控件的事件是否沿页的 UI 服务器控件层次结构向上传递。 

命名空间:System.Web.UI
程序集:System.Web(在 system.web.dll 中)

语法
Visual Basic(声明) 
Protected Overridable Function OnBubbleEvent ( _
    source As Object, _
    args As EventArgs _
) As Boolean
 
Visual Basic(用法) 
Dim source As Object
Dim args As EventArgs
Dim returnValue As Boolean

returnValue 
= Me.OnBubbleEvent(source, args)
 
C# 
protected virtual bool OnBubbleEvent (
    Object source,
    EventArgs args
)
 
C
++ 
protected:
virtual bool OnBubbleEvent (
    Object
^ source, 
    EventArgs
^ args
)
 
J# 
protected boolean OnBubbleEvent (
    Object source, 
    EventArgs args
)
 
JScript 
protected function OnBubbleEvent (
    source : Object, 
    args : EventArgs
) : boolean
 


参数
source
事件源。 

args
包含事件数据的 EventArgs 对象。 



返回值
如果事件已被取消,则为 
true;否则为 false。默认为 false。 
备注
ASP.NET 服务器控件(如 Repeater、DataList 和 DataGrid Web 控件)可以包含引发事件的子控件。例如,DataGrid 控件中的每一行都可以包含一个或多个由模板动态创建的按钮。不是由每个按钮分别引发事件,而是嵌套控件中的事件“冒泡”,即它们被发送到命名容器。命名容器然后引发带参数值的名为 ItemCommand 的一般事件。这些值使您可以确定引发原始事件的单个控件。通过响应这一事件,可以不必为子控件分别编写事件处理方法。

示例
下面的示例重写自定义 ASP.NET 服务器控件 ParentControl 中的 OnBubbleEvent 方法。在 ParentControl 的子控件调用 RaiseBubbleEvent 方法时会调用此方法。当这种情况发生时,ParentControl 类将两个字符串写入包含 ASP.NET 的页中,第一个字符串说明其 OnBubbleEvent 方法已被调用,第二个字符串标识 RaiseBubbleEvent 方法的源控件。

Visual Basic  复制代码 
Public Class ParentControl
   Inherits Control
   
   
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
   Protected Overrides Function OnBubbleEvent(sender As Object, e As EventArgs) As Boolean
      Context.Response.Write(
"<br><br>ParentControl's OnBubbleEvent called.")
      Context.Response.Write((
"<br>Source of event is: " + sender.ToString()))
      Return True
   End Function 
'OnBubbleEvent
   
   
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
   Protected Overrides Sub Render(myWriter As HtmlTextWriter)
      myWriter.Write(
"ParentControl")
      RenderChildren(myWriter)
   End Sub 
'Render
End Class 'ParentControl
 _

 
C#  复制代码 
public class ParentControl : Control 
{
   [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name
="FullTrust")] 
   
protected override bool OnBubbleEvent(object sender, EventArgs e)
   {
      Context.Response.Write(
"<br><br>ParentControl's OnBubbleEvent called.");
      Context.Response.Write(
"<br>Source of event is: " + sender.ToString());
      
return true;
   }
   [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name
="FullTrust")] 
   
protected override void Render( HtmlTextWriter myWriter)
   {
      myWriter.Write(
"ParentControl");
      RenderChildren(myWriter);
   }
}

至此上述方法和事件之间的关系总结如下图:



下面来研究OnItemCommand方法:
        protected virtual void OnItemCommand(DetailsViewCommandEventArgs e)
        {
            DetailsViewCommandEventHandler handler1 
= (DetailsViewCommandEventHandler) base.Events[DetailsView.EventItemCommand];
            
if (handler1 != null)
            {
                handler1(
this, e);
            }
        }
OnItemCommand方法被调用的地方:
        private bool HandleEvent(EventArgs e, bool causesValidation, string validationGroup)
        {
            
bool flag1 = false;
            
if (causesValidation && (this.Page != null))
            {
                
this.Page.Validate(validationGroup);
            }
            DetailsViewCommandEventArgs args1 
= e as DetailsViewCommandEventArgs;
            
if (args1 != null)
            {
                
this.OnItemCommand(args1);
                flag1 
= true;
                
string text1 = args1.CommandName;
                
int num1 = this.PageIndex;
                
if (StringUtil.EqualsIgnoreCase(text1, "Page"))
                {
                    
string text2 = (string) args1.CommandArgument;
                    
if (StringUtil.EqualsIgnoreCase(text2, "Next"))
                    {
                        num1
++;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "Prev"))
                    {
                        num1
--;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "First"))
                    {
                        num1 
= 0;
                    }
                    
else if (StringUtil.EqualsIgnoreCase(text2, "Last"))
                    {
                        
if (base.IsViewStateEnabled)
                        {
                            num1 
= this.PageCount - 1;
                        }
                        
else
                        {
                            num1 
= 0x7fffffff;
                        }
                    }
                    
else
                    {
                        num1 
= Convert.ToInt32(text2, CultureInfo.InvariantCulture) - 1;
                    }
                    
this.HandlePage(num1);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Edit"))
                {
                    
this.HandleEdit();
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Update"))
                {
                    
this.HandleUpdate((string) args1.CommandArgument, causesValidation);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Cancel"))
                {
                    
this.HandleCancel();
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Delete"))
                {
                    
this.HandleDelete((string) args1.CommandArgument);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "Insert"))
                {
                    
this.HandleInsert((string) args1.CommandArgument, causesValidation);
                    
return flag1;
                }
                
if (StringUtil.EqualsIgnoreCase(text1, "New"))
                {
                    
this.HandleNew();
                }
            }
            
return flag1;
        }
也是在HandleEvent方法中被调用的。
但是在HandleEvent方法中,OnItemCommand在HandleUpdate方法之前,这就是说,OnItemCommand中的Update方法,在OnItemUpdating和OnItemUpdated方法之前。
    在这里将前面的图完善一下:


下面看一下DataSourceID中对应的UpdateMethod方法的运行原理:



posted on   今夜太冷  阅读(894)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示