2010-01-28 4 views
1

클릭하면 명령 이벤트를 발생시켜야하는 동적으로 생성 된 이미지 버튼이있는 GridView가 있습니다. 이벤트 처리는 버튼을 처음 클릭하는 경우를 제외하고는 기본적으로 작동합니다. 그런 다음 다시 게시 처리되지만 이벤트가 발생하지 않습니다.ASP.NET : 이벤트가 실행되지 않고 포스트 백이 처리되었습니다.

이 코드를 디버깅하려고 시도한 결과, 첫 번째 클릭 전후에 실행 된 코드가 다른 모든 클릭과 완전히 동일하다고 생각됩니다. (첫 번째 클릭에서 이벤트 핸들러가 호출되지 않는다는 점을 제외하고는).

이벤트를 발생시키는 버튼은 데이터 바인딩을 통해 동적으로 생성됩니다. 즉, 데이터 바인딩은 데이터 바인딩을 통해 두 번 페이지 라이프 사이클 : 일단로드되면, 이벤트 처리 후 새 데이터를 표시하기 위해 버튼이 존재하도록 (그렇지 않으면 이벤트를 전혀 처리 할 수 ​​없게) 렌더링하기 전에 한 번로드합니다.

나는이 글을 읽고 있지만 내 상황과 일치하지 않을 : ASP.NET LinkButton OnClick Event Is Not Working On Home Page, LinkButton not firing on production server, ASP.NET Click() event doesn't fire on second postback

세부 사항에 :는 의 GridView 각 행에 이미지 버튼이 있습니다. 단추의 심상은 databound이다. 행은 GridView.DataBind()에 의해 생성됩니다. 이를 위해 CustomTemplate 구현과 함께 TemplateField를 사용했습니다. ItemTemplate의 InstantiateIn 메서드는 ImageButton을 만들고 해당 이벤트 처리기를 할당합니다. 또한 이미지의 DataBinding 이벤트에는 해당 행의 데이터를 기반으로 적절한 이미지를 검색하는 핸들러가 지정됩니다.

GridView는 UserControl에 배치됩니다. UserControl은 GridView의 이벤트에 대한 이벤트 처리기를 정의합니다.

private DataTable dataTable = new DataTable(); 
protected SPGridView grid; 

protected override void OnLoad(EventArgs e) 
{ 
    DoDataBind(); // Creates the grid. This is essential in order for postback events to work. 
} 

protected override void Render(HtmlTextWriter writer) 
{ 
    DoDataBind(); 
    base.Render(writer); // Renews the grid according to the latest changes 
} 

void ReadButton_Command(object sender, CommandEventArgs e) 
{ 
    ImageButton button = (ImageButton)sender; 
    GridViewRow viewRow = (GridViewRow)button.NamingContainer; 
    int rowIndex = viewRow.RowIndex; 

    // rowIndex is used to identify the row in which the button was clicked, 
    // since the control.ID is equal for all rows. 
    // [... some code to process the event ...] 
} 

private void DoDataBind() 
{ 
    // [... Some code to fill the dataTable ...] 

    grid.AutoGenerateColumns = false; 

    grid.Columns.Clear(); 

    TemplateField templateField = new TemplateField(); 
    templateField.HeaderText = ""; 
    templateField.ItemTemplate = new MyItemTemplate(new CommandEventHandler(ReadButton_Command)); 
    grid.Columns.Add(templateField); 

    grid.DataSource = this.dataTable.DefaultView; 
    grid.DataBind(); 
} 

private class MyItemTemplate : ITemplate 
{ 
    private CommandEventHandler commandEventHandler; 

    public MyItemTemplate(CommandEventHandler commandEventHandler) 
    { 
     this.commandEventHandler = commandEventHandler; 
    } 

    public void InstantiateIn(Control container) 
    { 
     ImageButton imageButton = new ImageButton(); 
     imageButton.ID = "btnRead"; 
     imageButton.Command += commandEventHandler; 
     imageButton.DataBinding += new EventHandler(imageButton_DataBinding); 
     container.Controls.Add(imageButton); 
    } 

    void imageButton_DataBinding(object sender, EventArgs e) 
    { 
     // Code to get image URL 
    } 
} 

그냥 반복 : 다음과 같이 코드는 대략 보이는 각각의 라이프 사이클에서 먼저의 OnLoad가 ImageButtons와 그리드를 생성하는 실행됩니다. 그런 다음 이벤트가 처리됩니다. 버튼이 있기 때문에 이벤트가 일반적으로 작동합니다. 그런 다음 Render가 호출되어 새로운 데이터를 기반으로 그리드를 처음부터 생성합니다. 페이지가 사용자에게 처음 전송 될 때 그리드 및 이미지 버튼이 생성된다는 것을 주장했지만 사용자가 이미지 버튼을 처음 클릭하는 경우를 제외하고는 항상 작동합니다.

누군가가 나를 이해하거나 내 상황에 대해 더 나은 해결책을 알려주기를 바랍니다.

답변

0

내 의견으로는이 부분 대답은, 내가 다시 포스트이기 때문에이 방법 :

  • 나는 똑같은 장소에 (대신 ImageButtons의 일반 버튼을 사용하는 경우, 즉 여전히 MyItemTemplate를 사용하지만 인스턴스 대신 "InstantiateIn"으로하여 ImageButton의 버튼, 그것을 작동 잘.

  • 내가 DoDataBind()는 항상 클라이언트에 컨텐츠를 전송하기 전에 두 번 실행된다는 주장하는 경우, 그것은 ImageButtons와 함께 잘 작동합니다.

여전히 어리둥절하지만 ...

3

여기 몇 가지 문제가 있습니다. 첫 번째는 IsPostBack 검사가 없다는 것입니다. 즉, 모든로드에서 데이터 바인딩 중임을 의미합니다.이 경우 발사되지 않는 이벤트를 포함하여 몇 가지 문제가 발생할 수 있습니다. 둘째, OnLoad 및 Render에서 호출하기 때문에 모든로드에서 DoDataBind()를 두 번 호출합니다. 왜?

데이터를 한 번 씩 묶은 다음 필요에 따라 이벤트에 반응하여 다시 바인딩하십시오.

기타 문제 ... 템플릿 필드의 ImageButton에 이벤트를 바인딩하지 마십시오. 이것은 일반적으로 작동하지 않습니다. ItemCommand 이벤트 및 CommandName/CommandArgument 값을 사용하십시오.

마지막으로 ... 마지막 질문 ... HTML에서 첫 번째로드에서 전체 페이지에서 렌더링 한 다음 비교 한 후 비교로드 (windiff 또는 기타 도구)를 수행 했습니까? 그들은 정확히 같은가요? 아니면 컨트롤 이름이나 PostBack 참조에 약간의 차이가 있습니까?

+0

안녕하세요. Bryan, 답장을 보내 주셔서 감사합니다. 내가 두 번 바인딩 이유는 위의 찾을 수 있습니다 : 첫 번째 시간 순서대로 이벤트가 해고 될 수 있도록 거기에되고; 이벤트 핸들러에 의해 변경된 사항에 따라 뷰를 갱신하기 위해 두 번째 시간. 포스트 백 후에 gridview를 databind하지 않으면 viewstate가 켜져 있어도 비어있는 것으로 판명됩니다. => ?? 따라서 모든 포스트 백 이후에 그리드를 데이터 바인딩해야합니다. – chiccodoro

+0

CommandField의 문제점은 이미지를 데이터 바인딩 할 수 없다는 것입니다 (?). 모든 행에 대해 하나의 동일한 이미지를 정의해야합니다. 내 경우에는 대조적으로 이미지를 표시하려면 각 행의 데이터에 의존해야합니다. BoundField는 차례로 명령 이벤트를 제공하지 않습니다. 그래서 템플릿은 제가 발견 한 유일한 방법입니다. 내가 틀렸다면 나에게 정정 해주세요, 나는 이것이 사실일지도 모른다! – chiccodoro

+0

두 HTML 파일 간의 차이점은 __REQUESTDIGEST, __EVENTVALIDATION, 그리고 물론 __VIEWSTATE에서 차이점을 나타 냈습니다. – chiccodoro

1

글쎄, 나는 페이지로드 후에 이벤트 디스 패칭이 일어난다 고 생각한다.이 경우 첫 번째 데이터 바인딩 시도로 생성 된 컨트롤에 대해 실행하려고 시도합니다. 이 컨트롤은 나중에 다시 만들 때와 다른 ID를 갖습니다. ASP.NET이 들어오는 이벤트를 컨트롤에 매핑하려고 시도하고 컨트롤을 찾지 못했다고 추측합니다.

실제 게시물의 내용을 캡처하는 것이 좋습니다.

ASP.NET은 이벤트 바인딩과 동적으로 생성 된 컨트롤에 있어서는 꽤 엉성합니다. 재미있게 보내십시오.

+0

고마워요, 프랭크. 재미있는 점은 일반적으로이 방법으로 작동한다는 것입니다. 문제는 첫 번째 포스트 백 이후에만 나타납니다. – chiccodoro

+0

두 가지 다른 흥미로운 세부 사항을 발견했습니다 : - ImageButtons ** 대신 ** Buttons를 사용하는 경우 (똑같은 장소, 즉 MyItemTemplate을 사용하지만 InstantiateIn에서 ImageButton 대신 Button을 인스턴스화하는 경우 ** 작동 함) 괜찮아요 ** ** - 여기에 나열되지 않은 내 코드의 일부 논리 때문에 OnLoad의 "DoDataBind()"메서드를 건너 뛰는 경우가 있습니다. 그래도 컨트롤은 렌더링의 DoDataBind() 호출에 의해 렌더링됩니다). 그러나 PostBack cycle * 이후에 사용자의 클릭 상호 작용은 처리되지 않습니다. – chiccodoro

+0

예 : 1. OnLoad() -> DoDataBind 건너 뛰기 1. Render() -> DoDataBind가 실행되고 컨트롤이 렌더링됩니다. 1. HTML을 클라이언트에 보냈습니다. 1. 클라이언트가 ImageButton을 클릭합니다. 1. PostBack이 서버로 전송되었습니다. 1. OnLoad() -> DoDataBind가 실행되었습니다. 1. 이벤트 전달이 실패합니다. 1. Render() -> DoDataBind가 실행되었습니다. 1. HTML을 클라이언트로 보냈습니다. 1. 클라이언트가 ImageButton을 클릭합니다. 1. PostBack이 서버로 전송되었습니다. 1. OnLoad() -> DoDataBind가 실행되었습니다. 1. 이벤트가 시작됩니다. ... => DoDataBind()가 클라이언트에 내용을 보내기 전에 항상 두 번 실행된다고 주장하면 작동합니다! – chiccodoro

관련 문제