2008-09-05 37 views
7

Tôi có một trang khá phức tạp tự động xây dựng các điều khiển người dùng bên trong bộ lặp. Bộ lặp này phải bị ràng buộc trong sự kiện trang Init trước khi ViewState được khởi tạo hoặc các điều khiển người dùng được tạo động sẽ không giữ lại trạng thái của chúng.Bạn sẽ làm gì khi không thể sử dụng ViewState?

Điều này tạo ra một Catch-22 thú vị bởi vì đối tượng tôi liên kết bộ lặp cần phải được tạo trên tải trang ban đầu, và sau đó tiếp tục tồn tại trong bộ nhớ cho đến khi người dùng chọn thoát hoặc lưu.

Vì tôi không thể sử dụng ViewState để lưu trữ đối tượng này, nhưng đã có sẵn trong Init, tôi đã bị buộc phải lưu trữ nó trong phiên.

Điều này cũng có vấn đề, bởi vì tôi phải vô hiệu hóa giá trị phiên trong thời gian không đăng lại để mô phỏng cách hoạt động của ViewState.

Có một cách tốt hơn để quản lý trạng thái trong trường hợp này. Bất kỳ ý tưởng?

Chỉnh sửa: Một số gợi ý hay về cách sử dụng LoadViewState, nhưng tôi vẫn gặp sự cố với trạng thái không được khôi phục khi tôi làm điều đó.

Đây là phần nào nếu cấu trúc trang

Trang -> UserControl -> Repeater -> N lượng UserControls dynamicly tạo.

Tôi đặt ghi đè LoadViewState trong phụ huynh UserControl vì thiết kế được đóng gói hoàn toàn và độc lập với trang đang bật. Tôi tự hỏi nếu đó là nơi mà vấn đề là.

Trả lời

1

Điều này cũng có vấn đề, bởi vì tôi phải bỏ qua giá trị phiên trong thời gian không đăng lại để mô phỏng cách hoạt động của ViewState.

Tại sao bạn để bỏ trống giá trị (ngoài quản lý bộ nhớ, v.v ...)? Nó không phải là một tùy chọn để kiểm tra Page.IsPostback, và làm một cái gì đó với biến Session hay không?

1

Tôi luôn tạo lại các điều khiển động trong sự kiện LoadViewState. Bạn có thể lưu trữ số lượng điều khiển cần thiết để tạo ra trong ViewState và sau đó tự động tạo ra rằng nhiều người trong số họ bằng cách sử dụng phương pháp LoadControl bên trong sự kiện LoadViewState. Trong trường hợp này, bạn có quyền truy cập vào ViewState nhưng chưa được khôi phục vào các điều khiển trên trang.

0

@DancesWithBamboo:

Nếu tôi tự động liên kết điều khiển ở đó, ASP.NET có tự động xử lý trạng thái của họ không? Vấn đề với việc thực hiện nó trong Page_Load là viewstate đã được nạp và nó không thêm các điều khiển động trong bộ lặp. Tôi sẽ nghĩ rằng nó sẽ làm như vậy trong LoadViewState?

+0

Bạn đang sử dụng databinding? Tôi không bao giờ sử dụng nó với asp.net và nó có thể thay đổi lĩnh vực chơi một chút. Tuy nhiên, LoadViewState là sự kiện sẽ được sử dụng để khôi phục các điều khiển động ở thời gian sau. PageLoad chắc chắn là quá muộn trong vòng đời. – DancesWithBamboo

0

1) có thể là một cách để làm cho nó hoạt động ... bạn chỉ cần chắc chắn để thêm điều khiển của bạn vào cây vào đúng thời điểm. Quá sớm và bạn không nhận được ViewState. Quá muộn và bạn không nhận được ViewState.

2) Nếu bạn không thể tìm ra, có thể bạn có thể tắt chế độ xem cho trang lỗ và sau đó chỉ dựa trên chuỗi truy vấn để thay đổi trạng thái? Bất kỳ liên kết nào trước đây là đăng lại sẽ là liên kết tới một URL khác (hoặc chuyển hướng đăng lại).

Điều này thực sự có thể làm giảm trọng lượng của trang và giúp tránh các vấn đề với ViewState dễ dàng hơn.

0

@ Jonathan:

Có, thời gian chạy sẽ cư trú trong chế độ xem kiểm soát miễn là bạn tạo đúng số lượng của chúng. Viewstate của các điều khiển sẽ cư trú sau sự kiện này.

0

Có, thời gian chạy sẽ cư trú trong chế độ xem của các điều khiển miễn là bạn tạo đúng số lượng của chúng. Viewstate của các điều khiển sẽ cư trú sau sự kiện này.

Thứ tự LoadViewState được gọi là gì? Tôi đã thêm một chữ ký phương thức ghi đè và nó dường như không bước vào nó.

0
protected override void LoadViewState(object savedState) 
{ 
    // Put your code here before base is called 
    base.LoadViewState(savedState); 
} 

Đó có phải là ý của bạn không? Hay bạn có ý nghĩa gì trong các điều khiển được xử lý? Tôi nghĩ câu trả lời cho điều đó là nó gần như ngẫu nhiên.

Ngoài ra, tại sao bạn không thể tải các đối tượng bạn liên kết trước Page_Load? Bạn có thể gọi lớp doanh nghiệp của mình bất kỳ lúc nào trong vòng đời của trang nếu bạn có, ngoại trừ việc hiển thị trước và mọi thứ sau đó.

0

Tôi phải hủy giá trị phiên trong thời gian không đăng lại để mô phỏng cách hoạt động của ViewState.

Tôi vẫn còn sương mù là lý do tại sao bạn không thể lưu trữ bất kỳ đối tượng nào bạn đang ràng buộc trong phiên. Nếu bạn có thể lưu trữ đối tượng đó trong phiên, các mục sau sẽ hoạt động:

  1. Lần tải đầu tiên liên kết điều khiển người dùng hàng đầu của bạn với đối tượng trong OnPreInit. Lưu trữ đối tượng trong phiên. Viewstate sẽ tự động được lưu trữ cho các điều khiển đó. Nếu bạn phải liên kết điều khiển lần đầu tiên trên Page_Load đó là ok, nhưng bạn sẽ kết thúc có hai sự kiện gọi ràng buộc nếu bạn làm theo bước tiếp theo.
  2. Khi đăng lại, hãy khôi phục quyền kiểm soát người dùng trên cùng của bạn bằng phương pháp OnPreInit đối với đối tượng bạn đã lưu trong phiên. Tất cả các điều khiển của bạn nên được tái tạo trước khi tải viewstate. Sau đó, khi viewstate được khôi phục, các giá trị sẽ được đặt thành bất kỳ giá trị nào trong viewstate. Chỉ báo trước ở đây là khi bạn liên kết lại trên postback, bạn phải chắc chắn 100% rằng cùng một số điều khiển được tạo lại. Chìa khóa để sử dụng Repeater, Gridviews vv ... với các điều khiển động bên trong chúng là chúng để được phục hồi trên mọi postback trước khi viewstate được tải. OnPreInit thường là nơi tốt nhất để làm điều này. Không có ràng buộc kỹ thuật trong khuôn khổ mà quy định rằng bạn phải làm tất cả công việc của bạn trong Page_Load trên lần tải đầu tiên.

Điều này sẽ hiệu quả. Tuy nhiên, nếu bạn không thể sử dụng phiên vì lý do nào đó, thì bạn sẽ phải thực hiện một cách tiếp cận hơi khác như lưu trữ bất cứ thứ gì bạn ràng buộc trong cơ sở dữ liệu sau khi bạn kiểm soát, sau đó kéo nó ra khỏi cơ sở dữ liệu và rebinding một lần nữa trên mỗi postback.

Tôi có thiếu một số chi tiết rõ ràng về tình huống của bạn không? Tôi biết nó có thể rất phức tạp để giải thích sự tinh tế của tình huống mà không cần đăng mã.

EDIT: Tôi đã thay đổi tất cả các tham chiếu thành OnInit thành OnPreInit trong giải pháp này.Tôi quên rằng MS đã giới thiệu sự kiện mới này trong ASP.NET 2.0. Theo số page lifecycle documentation, OnPreInit là nơi mà các điều khiển động sẽ được tạo/tái tạo.

0

Khi tạo điều khiển động ... Tôi chỉ điền chúng vào tải ban đầu. Sau đó tôi tạo lại các điều khiển trên postback trong sự kiện tải trang, và ViewState dường như xử lý việc repopulating các giá trị mà không có vấn đề gì.

4

Phương thức LoadViewState trên trang chắc chắn là câu trả lời. Dưới đây là hướng dẫn chung:

protected override void LoadViewState(object savedState) { 
    var savedStateArray = (object[])savedState; 

    // Get repeaterData from view state before the normal view state restoration occurs. 
    repeaterData = savedStateArray[ 0 ]; 

    // Bind your repeater control to repeaterData here. 

    // Instruct ASP.NET to perform the normal restoration of view state. 
    // This will restore state to your dynamically created controls. 
    base.LoadViewState(savedStateArray[ 1 ]); 
} 

SaveViewState cần để tạo ra các mảng savedState mà chúng ta đang sử dụng trên:

protected override object SaveViewState() { 
    var stateToSave = new List<object> { repeaterData, base.SaveViewState() }; 
    return stateToSave.ToArray(); 
} 

Đừng quên cũng để ràng buộc các repeater trong Init hoặc Load sử dụng mã như thế này:

if(!IsPostBack) { 
    // Bind your repeater here. 
} 
Các vấn đề liên quan