2009-09-18 29 views
6

Gọi một hàm từ MasterPage trong một trang là khá straigt về phía trước nhưng làm thế nào để tôi gọi nó cho một UserControl:ASP.NET: Gọi hàm trong MasterPage qua UserControl

Thêm <%@ MasterType VirtualPath="~/MasterPage.master" %>, không hoạt động trên UserControls.

Vì vậy this.Page.Master.MyFunction() thất bại :(

Trả lời

7

Niels,

Phản xạ đòn bẩy (theo đề xuất của JDunkerley) là một cách tiếp cận cho vấn đề. Bạn có thể xem xét việc triển khai giao diện khác:

  1. Tạo giao diện bao gồm phương pháp của bạn.
  2. Triển khai giao diện trong trang chính của bạn
  3. Từ kiểm soát của bạn, hãy tham khảo this.Page.Master thông qua loại giao diện.
  4. Gọi phương thức của bạn.

Đây là cách tiếp cận OO tốt hơn, dẫn đến ít khớp nối hơn và chắc chắn sẽ hoạt động tốt hơn so với phản xạ thời gian chạy.

Tôi hy vọng điều này sẽ hữu ích!

+0

Tôi đã sử dụng cách tiếp cận này và nó hoạt động tốt! Cảm ơn –

+0

Rất vui được trợ giúp! Happy code :-) –

12

Bạn phải cast this.Page.Master đầu tiên như Master tài sản của Trang là loại System.Web.UI.MasterPage.

ví dụ

((MyMaster)this.Page.Master).MyFunction(); 

Bạn có thể kiểm tra loại trang cái cơ bản bằng cách thêm thuộc tính vào mã phía sau điều khiển người dùng:

public string MType 
    { 
     get { return this.Page.Master.GetType().FullName; } 
    } 

và in kết quả ra trong đánh dấu Kiểm soát người dùng, ví dụ: thêm dòng này để làm cho nó in ra dưới dạng nhận xét trong mã nguồn:

<!-- <%= MType %> //--> 
+0

Tôi gặp lỗi khi nói rằng nó không thể tìm thấy loại hoặc không gian tên _Master ?? –

+0

bạn có thể thử kiểm tra loại trang chính tại RunTime. Sẽ cập nhật câu trả lời trong một giây thứ hai – JDunkerley

+0

Loại là ASP.masterpage_master nhưng không có sẵn trong thời gian biên dịch. –

4

Bạn đang chuyển đổi mã của bạn rất thành thật nếu bạn gọi một hàm trên trang chủ từ bên trong điều khiển người dùng của bạn.

Điều khiển chỉ có thể được sử dụng trên các trang dựa trên tổng thể đó. Tôi nghĩ rằng đây thường là một thiết kế tồi, và nó sẽ vi phạm ít nhất luật của Demeter.

Chính xác những gì bạn muốn thực hiện trong tầm kiểm soát của mình?

1

JDunkerley đã đúng. Nhưng hãy để tôi giải thích cách tách nó ra bằng cách sử dụng MVP để bạn có thể làm việc hướng tới việc tránh vấn đề thiết kế mà Heiko Hatzfeld đang nói đến.

Về cơ bản, triển khai mẫu MVP cho cả điều khiển của bạn và trang cái của bạn. Xem here để biết hướng dẫn về cách thực hiện điều đó. Khai báo phương thức bạn muốn gọi trong giao diện chính (IMasterView). Tiếp theo tạo một lớp sẽ kiểm soát mối quan hệ giữa hai thành phần; chúng ta sẽ gọi nó là lớp PageController. Đặt một thể hiện của lớp này trong trạng thái yêu cầu cho mỗi yêu cầu bằng cách thêm dòng sau vào global.asax.cs:

/* global.asax.cs */ 
protected void Application_BeginRequest(object sender, EventArgs e) 
{ 
    // ... 
    HttpContext.Current.Items["Controller"] = new PageController(); 
    // ... 
} 

Sau đó bạn có thể truy cập vào trường hợp này từ mỗi người thuyết trình (tổng thể và kiểm soát) thông qua dòng mã sau đây:

var controller = HttpContext.Current.Items["Controller"] as PageController; 

Sau đó bạn có thể thực hiện một sự kiện hoặc một số cơ chế khác để cho phép điều khiển gọi phương thức trên máy chủ theo cách được tách riêng thông qua đối tượng được chia sẻ này. Ví dụ:

/* PageController.cs */ 
public event EventHandler SomeEvent; 

protected virtual void OnSomeEvent(EventArgs e) 
{ 
    Debug.Assert(null != e); 

    var handler = this.SomeEvent; 
    if (null != handler) 
     handler(this, e); 
} 

public void FireSomeEvent() 
{ 
    this.OnSomeEvent(EventArgs.Empty); 
} 

/* ControlPresenter.cs */ 
public ControlPresenter(IControlView view) 
    : base() 
{ 
    view.EventFired += (sender, e) => 
    { 
     var controller = HttpContext.Current.Items["Controller"] as PageController; 
     controller.FireSomeEvent(); 
    }; 
} 

/* MasterPresenter.cs */ 
public MasterPresenter (IMasterView view) 
    : base() 
{ 
    var controller = HttpContext.Current.Items["Controller"] as PageController; 
    controller.SomeEvent += (sender, e) => view.MyFunction(); 
} 

Đảm bảo sự kiện "EventFired" được khai báo trong giao diện điều khiển của bạn (IControlView) và được thực hiện trong kiểm soát. Sau đó, tất cả các bạn phải làm để ảnh hưởng đến chủ (gọi phương thức của nó), là cháy sự kiện này và MVP + PageContoller sẽ chăm sóc phần còn lại.

Cheers

1

tôi không thể có được câu trả lời ở trên để làm việc, vì vậy đây là những gì làm việc cho tôi:

Bạn muốn tham khảo một tài sản trang chủ từ một điều khiển người dùng.

Thứ nhất, trang chủ của bạn sẽ có một tài sản công cộng như vậy:

public string BodyClass 
{ 
    set 
    { 
     this.masterBody.Attributes.Add("class", value); 
    } 
} 

Bây giờ thêm một tham chiếu đến trang chủ trong file ascx điều khiển người dùng như vậy:

<%@ Register Src="~/Source/MasterPages/Main.master" TagPrefix="MSTR" TagName="MasterPage" %> 

Sau đó, trong mã phía sau (C# trong trường hợp của tôi) bạn có mã này:

Main masterPage = (Main)this.Page.Master; 
masterPage.BodyClass = "container"; 

Không có tham chiếu đến trang chính phía trên điều khiển người dùng của bạn sẽ không thể tìm thấy lớp trang chính.

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