2009-04-29 18 views
33

Tôi đang có những gì tôi tin là một vấn đề khá đơn giản, nhưng đối với cuộc sống của tôi, tôi không thể thấy được vấn đề của mình. Vấn đề có liên quan đến ScriptManager.RegisterStartupScript, một cái gì đó tôi đã sử dụng nhiều lần trước đây.Không thể lấy ScriptManager.RegisterStartupScript trong WebControl lồng trong UpdatePanel để làm việc

Kịch bản tôi có là tôi có một điều khiển web tùy chỉnh đã được chèn vào một trang. Kiểm soát (và một hoặc hai người khác) được lồng trong UpdatePanel. Chúng được chèn vào trang vào PlaceHolder:

<asp:UpdatePanel ID="pnlAjax" runat="server"> 
    <ContentTemplate> 
    <asp:PlaceHolder ID="placeholder" runat="server"> 
    </asp:PlaceHolder> 
    ... 

protected override void OnInit(EventArgs e){ 
    placeholder.Controls.Add(Factory.CreateControl()); 
    base.OnInit(e); 
} 

Đây là bảng cập nhật duy nhất trên trang.

Kiểm soát yêu cầu một số javascript ban đầu được chạy để hoạt động chính xác. Các cuộc gọi kiểm soát:

ScriptManager.RegisterStartupScript(this, GetType(), 
            Guid.NewGuid().ToString(), script, true); 

và tôi cũng đã cố gắng:

ScriptManager.RegisterStartupScript(Page, Page.GetType(), 
            Guid.NewGuid().ToString(), script, true); 

Vấn đề là kịch bản chạy một cách chính xác khi trang được hiển thị đầu tiên, nhưng không chạy lại sau khi một postback một phần. Tôi đã thử những điều sau đây:

  1. Calling RegisterStartupScript từ CreateChildControls
  2. Calling RegisterStartupScript từ onload/OnPreRender
  3. Sử dụng kết hợp khác nhau của các tham số cho hai tham số đầu tiên (trong ví dụ trên Control là Page và Type là GetType(), nhưng tôi đã thử bằng cách sử dụng kiểm soát chính nó, vv).
  4. Tôi đã thử sử dụng id liên tục và mới (không phải là tôi tin rằng điều này sẽ có tác động lớn theo một trong hai cách).
  5. Tôi đã sử dụng một vài điểm ngắt và do đó đã xác minh rằng dòng Đăng ký đang được gọi chính xác.

Điều duy nhất tôi chưa thử là sử dụng UpdatePanel như Kiểm soát và Loại, vì tôi không tin rằng điều khiển nên nhận biết bảng điều khiển cập nhật (và trong mọi trường hợp có vẻ không phải là cách tốt để nhận bảng cập nhật?).

Có ai có thể thấy những gì tôi có thể làm sai ở trên không?

Cảm ơn :)


Vâng, để trả lời các truy vấn trên - nó xuất hiện như là nếu giữ chỗ bằng cách nào đó messes lên ScriptManager.RegisterStartupScript.

Khi tôi kéo điều khiển ra khỏi trình giữ chỗ và mã trực tiếp lên trang, tập lệnh Đăng ký hoạt động chính xác (tôi cũng đang sử dụng điều khiển chính nó làm tham số).

 

ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true); 

Ai có thể ném bất kỳ ánh sáng nào vào lý do tại sao điều khiển được tiêm vào PlaceHolder sẽ ngăn ScriptManager đăng ký đúng kịch bản không? Tôi đoán điều này có thể có một cái gì đó để làm với vòng đời của điều khiển năng động, nhưng sẽ đánh giá cao (cho kiến ​​thức của riêng tôi) nếu có một quá trình chính xác cho các bên trên.

Trả lời

14

Tôi nghĩ bạn thực sự nên sử dụng Control overload của RegisterStartupScript.

Tôi đã thử đoạn mã sau vào một điều khiển server:

[ToolboxData("<{0}:AlertControl runat=server></{0}:AlertControl>")] 
public class AlertControl : Control{ 
    protected override void OnInit(EventArgs e){ 
     base.OnInit(e); 
     string script = "alert(\"Hello!\");"; 
     ScriptManager.RegisterStartupScript(this, GetType(), 
         "ServerControlScript", script, true); 
    } 
} 

Sau đó, trong trang của tôi, tôi có:

protected override void OnInit(EventArgs e){ 
    base.OnInit(e); 
    Placeholder1.Controls.Add(new AlertControl()); 
} 

đâu Phần giữ chỗ 1 là một giữ chỗ trong một bảng cập nhật. Trình giữ chỗ có một vài điều khiển khác trong đó, bao gồm các nút.

Hành vi này chính xác như bạn mong đợi, tôi nhận được thông báo "Xin chào" mỗi lần tôi tải trang hoặc khiến bảng cập nhật cập nhật.

Điều khác mà bạn có thể nhìn vào là để móc vào một số sự kiện trang vòng đời được bắn trong một yêu cầu cập nhật bảng điều khiển:

Sys.WebForms.PageRequestManager.getInstance() 
    .add_endRequest(EndRequestHandler); 

Ngọn lửa PageRequestManager endRequestHandler sự kiện mỗi khi một bảng cập nhật hoàn thành bản cập nhật của nó - điều này sẽ cho phép bạn gọi một phương thức để thiết lập quyền kiểm soát của bạn.

chỉ thắc mắc khác của tôi là:

  • gì được kịch bản của bạn thực sự đang làm gì?
  • Có lẽ bạn có thể xem tập lệnh trong HTML ở cuối trang (ngay trước thẻ đóng </form >)?
  • Bạn đã thử đặt một vài "cảnh báo" ("Đây"); " các cuộc gọi trong tập lệnh khởi động của bạn để xem nó có được gọi chính xác không?
  • Bạn đã thử Firefox và Firebug - có phải báo cáo bất kỳ lỗi tập lệnh nào không?
+0

Hi Ben, cảm ơn câu trả lời. Tại thời điểm này, kịch bản chỉ đơn giản là kích hoạt một cảnh báo, không có gì hơn. Nó là một điều khiển lưới, kế thừa datagrid. Tôi thường sử dụng Firefox/Bug, nhưng trong trường hợp này tôi đang làm việc trong một ứng dụng chỉ có IE (không phải lựa chọn của tôi), sẽ không thể truy cập vào màn hình trong FF. Sử dụng thanh công cụ IE Dev, tôi có thể kiểm tra trang, nhưng kịch bản đã không đăng ký lại trên postback. Tôi thích ý tưởng của PageRequestManager, mặc dù kịch bản không dễ tiếp xúc với trang để gọi như một trình xử lý.Tôi thích những ý tưởng tho, và sẽ sử dụng những điều này để điều tra thêm, nhờ – Chris

10

Khi bạn gọi ScriptManager.RegisterStartupScript, thông số "Kiểm soát" phải là điều khiển nằm trong UpdatePanel sẽ được cập nhật.Bạn cần phải thay đổi nó thành:

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true); 
+0

Có - Tôi đã thử sử dụng chính điều khiển được lồng trong UpdatePanel. Điều khiển được chèn vào phần giữ chỗ, nhưng tôi tin rằng điều này sẽ ổn? – Chris

1

Giải pháp là để đưa kịch bản trong tập tin một bên ngoài js (cho phép gọi là 'yourDynamic.js') và đăng ký lại tập tin de mọi lúc bạn làm mới updatepanel.

tôi sử dụng này trong trường hợp updatepanel_prerender:

ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _ 
        "<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _ 
        "include('yourDynamic.js');" & _ 
        "removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _ 
        , False) 

Trong trang hoặc trong một số khác bao gồm, bạn sẽ cần javascript này:

// Include a javascript file inside another one. 
function include(filename) 
{ 
    var head = document.getElementsByTagName('head')[0]; 

    var scripts = document.getElementsByTagName('script'); 
    for(var x=0;x<scripts.length;> { 
     if (scripts[x].getAttribute('src')) 
     { 
      if(scripts[x].getAttribute('src').indexOf(filename) != -1) 
      { 
       head.removeChild(scripts[x]); 
       break; 
      } 
     } 
    } 

    script = document.createElement('script'); 
    script.src = filename; 
    script.type = 'text/javascript'; 
    head.appendChild(script) 
} 

// Removes duplicated scripts. 
function removeDuplicatedScript(id) 
{ 
    var count = 0; 
    var head = document.getElementsByTagName('head')[0]; 

    var scripts = document.getElementsByTagName('script'); 
    var firstScript; 
    for(var x=0;x<scripts.length;> { 
     if (scripts[x].getAttribute('id')) 
     { 
      if(scripts[x].getAttribute('id').indexOf(id) != -1) 
      { 
       if (count == 0) 
       { 
        firstScript = scripts[x]; 
        count++; 
       } 
       else 
       { 
        head.removeChild(firstScript); 
        firstScript = scripts[x]; 
        count = 1; 
       } 
      } 
     } 
    } 
    clearAjaxNetJunk(); 
} 
// Evoids the update panel auto generated scripts to grow to inifity. X-(
function clearAjaxNetJunk() 
{ 
    var knowJunk = 'Sys.Application.add_init(function() {'; 
    var count = 0; 
    var head = document.getElementsByTagName('head')[0]; 

    var scripts = document.getElementsByTagName('script'); 
    var firstScript; 
    for(var x=0;x<scripts.length;> { 
     if (scripts[x].textContent) 
     { 
      if(scripts[x].textContent.indexOf(knowJunk) != -1) 
      { 
       if (count == 0) 
       { 
        firstScript = scripts[x]; 
        count++; 
       } 
       else 
       { 
        head.removeChild(firstScript); 
        firstScript = scripts[x]; 
        count = 1; 
       } 
      } 
     } 
    } 
} 

Khá mát mẻ, ah ... jejeje này một phần của những gì tôi đã đăng một thời gian trước đây here.

Hope trợ giúp này ... :)

+0

Hmmm, cơ chế thú vị - Tôi có thể thấy nó sẽ hữu ích như thế nào trong một vài trường hợp. Không chắc chắn 100% điều này sẽ giải quyết nó cho tôi, vì bất kỳ js nào được chèn vào thông qua trình quản lý kịch bản đều bị bỏ qua bởi UpdatePanel - tôi thậm chí không thể nhận được cảnh báo ('hello world'); chạy! Không phải khi nó được nhúng vào phần giữ chỗ ở bất kỳ giá nào :(Sẽ cho nó một tho tho, luôn sẵn sàng để được bác bỏ :) – Chris

+0

Hãy nhớ rằng ở đây chèn được thực hiện bởi javascript, thats những gì làm cho nó rất năng động. Cho tôi biết nếu nó hoạt động. – Lucas

+0

Ồ ... và hãy nhớ rằng cuộc gọi đến RegisterClientScriptBlock phải nằm trong sự kiện khởi chạy lại updatepanel ... :) – Lucas

1

Tôi đã có một vấn đề với Page.ClientScript.RegisterStartUpScript - Tôi đã không sử dụng một bảng cập nhật, nhưng kiểm soát được lưu trữ. Điều này có nghĩa rằng tôi đã phải chèn các kịch bản vào một Literal (hoặc có thể sử dụng một PlaceHolder) vì vậy khi kết xuất từ ​​bộ nhớ cache kịch bản được bao gồm.

Một giải pháp tương tự có thể phù hợp với bạn.

+0

Cảm ơn - Tôi sẽ điều tra chuỗi chữ, có thể là giải pháp tốt. Tôi đang sử dụng một kỹ thuật chèn khác nhau như tôi đang sử dụng phương pháp tĩnh tắt System.Web.Ui.ScriptManager, không phải là cơ chế Page.ClientScript – Chris

0

tôi cố gắng nhiều thứ và cuối cùng phát hiện ra rằng các tham số cuối cùng phải là sai lầm và bạn phải thêm <SCRIPT> thẻ để kịch bản java:

string script = "<SCRIPT>alert('hello!');< /SCRIPT>"; 

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**); 
+2

Thiết lập đúng cho tham số cuối cùng sẽ tự động thêm các thẻ script. – cjk

33

Tôi đã có một vấn đề sử dụng điều này trong một điều khiển người dùng (trong một trang này hoạt động tốt); Button1 nằm trong một số updatepanelscriptmanager nằm trên usercontrol.

protected void Button1_Click(object sender, EventArgs e) 
{ 
    string scriptstring = "alert('Welcome');"; 
    ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true); 
} 

Bây giờ có vẻ như bạn phải cẩn thận với hai đối số đầu tiên, họ cần phải tham khảo trang web của bạn, không kiểm soát của bạn

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true); 
0

gì làm việc cho tôi, được đăng ký vào trang trong khi chỉ định loại như của UpdatePanel, như vậy:

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true); 
0

Đôi khi nó không cháy khi tập lệnh có lỗi cú pháp, hãy đảm bảo cú pháp tập lệnh và javascript là chính xác.

+0

nhận xét khác –

1

KHÔNG Sử dụng GUID Đối với chính

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) 
     Guid.NewGuid().ToString(), myScript, true); 

và nếu bạn muốn làm điều đó, hãy gọi cái gì đó giống như chức năng này

public static string GetGuidClear(string x) 
{ 
     return x.Replace("-", "").Replace("0", "").Replace("1", "") 
       .Replace("2", "").Replace("3", "").Replace("4", "") 
       .Replace("5", "").Replace("6", "").Replace("7", "") 
       .Replace("8", "").Replace("9", ""); 
} 
0
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script, true); 

Các "true" giá trị param vào cuối ScriptManager.RegisterStartupScript sẽ thêm thẻ JavaScript vào trang của bạn:

<script language='javascript' defer='defer'>your script</script > 

Nếu giá trị sẽ là "sai", nó sẽ chỉ tiêm tập lệnh witout thẻ --script--.

Các vấn đề liên quan