2010-03-25 35 views
14

Vì vậy, lệnh gọi phương thức InitializeComponent trong trình tạo của Window đang chạy qua XML và thêm các điều khiển và cắm chúng vào các sự kiện của chúng.WPF Kiểm soát tham chiếu null trong InitializeComponent

Vì vậy, khi thuộc tính của một trong các điều khiển thay đổi, nó gọi Phương thức đăng ký sự kiện. Phương thức này tham chiếu đến một điều khiển chưa được xây dựng.

Tại sao điều này xảy ra theo thứ tự này tại đây? Nó hoạt động trong WinForms vì các sự kiện không được kích hoạt cho đến sau này, sau khi tất cả các điều khiển được tạo ra. Có cách nào để buộc điều này trong WPF?

Các giải pháp khác mà tôi thấy là

  • tôi cần phải đăng ký vào các sự kiện sau khi khởi tạo.

  • Tôi cần phải kiểm tra null bất cứ khi nào tôi xử lý kiểm soát.

+0

Sẽ hữu ích khi biết cụ thể sự kiện nào đang gây ra sự cố - bạn có thể thêm chi tiết hơn không? Tuy nhiên tôi nghi ngờ câu trả lời có thể là điểm đầu tiên của bạn ... –

+0

Bạn có thể giải thích thêm về kiến ​​trúc này không? Tôi tò mò tại sao một tài sản sẽ chứa đăng ký sự kiện. –

Trả lời

23

Tôi vừa gặp vấn đề này và giải quyết vấn đề bằng cách gói dòng truy cập điều khiển rỗng trong kiểm tra rỗng. Điều này có vẻ như một chút của một workaround hack. Tôi nghĩ WPF đang cố gắng hữu ích ở đây bằng cách gọi sự kiện được kiểm tra của chúng tôi trong InitializeComponent(), nhằm đảm bảo rằng bất kỳ logic UI nào (ví dụ: hiển thị/ẩn các thành phần liên quan) được thực hiện dựa trên trạng thái ban đầu của hộp kiểm . Tôi đã thử nghiệm có Checkbox không được kiểm tra theo mặc định, và xử lý sự kiện không được gọi, mặc dù tôi có nó có dây cho cả các sự kiện Checked và Unchecked. Tôi thậm chí tái tạo điều này trong một dự án WPF trống với một Checkbox duy nhất trên màn hình, và nó hoạt động như nhau.

Vấn đề với hành vi mặc định này rõ ràng là một số thành phần khác chưa được khởi tạo. Tôi nghĩ rằng WPF nên đợi cho đến khi tất cả các thành phần được khởi tạo trước khi kích hoạt sự kiện Checked theo mặc định.Điều này có thể không được coi là lỗi, nhưng tôi sẽ thêm ghi chú vào trang MSDN có liên quan ...

0

Có bất kỳ điều khiển nào sử dụng dữ liệu hai chiều không? Tôi đã chạy vào vấn đề này, nơi tôi đã có hộp văn bản bị ràng buộc vào một thuộc tính trên một ViewModel. Việc khởi tạo ViewModel đã kích hoạt INotifyPropertyChanged lên đến kiểm soát bị ràng buộc, do đó gây ra sự kiện TextChanged của hộp văn bản để kích hoạt. Giải pháp ngắn hạn của tôi là di chuyển đăng ký sự kiện vào cửa sổ Sự kiện được tải, nhưng giống như bạn nói, đó là một nỗi đau. Tôi cần phải refactor mã để thay đổi thứ tự trong cách đối tượng của tôi được khởi tạo, để xem WPF (tức là cửa sổ và điều khiển người dùng) được tạo ra trước khi ViewModels. Sau đó, tôi sẽ có thể di chuyển đăng ký trình xử lý sự kiện trở lại XAML.

+0

Tôi không sử dụng bất kỳ dữ liệu thời gian biên dịch nào. – rediVider

4

Bạn sẽ có thể kiểm tra các thuộc tính IsInitialized hoặc IsLoaded trên Cửa sổ của mình để xác minh nó đã hoàn tất việc khởi tạo/tải. Nếu không, bạn sẽ cần phải kiểm tra null hoặc thêm đăng ký sự kiện của bạn trong mã của bạn phía sau (sau khi InitializeComponent).

Ngoài ra, bạn có thể điều chỉnh cách bạn truy cập các yếu tố. Ví dụ, nếu bạn có một cái gì đó như:

<ListBox x:Name="listBox" SelectionChanged="OnListBoxSelectionChanged" /> 

Sau đó, trong mã của bạn phía sau bạn có thể nhận được các hộp danh sách nhiều cách:

private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { 
    ListBox lb = this.listBox; // May be null 
    ListBox lb = sender as ListBox; // Should never be null 
    ListBox lb = e.Source as ListBox; // Same as sender in this case 
    ListBox lb = e.OriginalSource as ListBox; // Always the element that started the event (if handler is not attached directly to ListBox). 
    // ... Do Something ... 
} 
+0

Tôi có biểu mẫu bận với hằng số en/ab-abling. Tôi đoán tôi sẽ phải di chuyển các đăng ký sự kiện đến constructor sau khi init chạy. – rediVider

5

Đó là trường hợp kiểm tra trên một RadioButton. Khi tôi gỡ bỏ kiểm tra = "true" từ xaml vấn đề đã biến mất. (mặc dù nó được kiểm tra khi cửa sổ khởi động). Không chắc chuyện gì đang diễn ra ở đây, nhưng ít nhất tôi không phải thay đổi bất cứ thứ gì lớn để sửa nó ...

+0

Cảm ơn rediVider, giải pháp của bạn đã làm việc cho tôi (Tôi đã sử dụng .NET 4.5.1). –

0

Điều khiển cửa sổ kích hoạt Sự kiện được kiểm tra khi khởi tạo các điều khiển phụ có thể được kiểm tra và được đặt để kiểm tra như ban đầu giá trị.

Tôi mạnh mẽ cho rằng đây là lỗi. Chỉ cần thực tế là nó bắn một NullReferenceException từ sâu trong hội đồng MFC nên là đủ để mong đợi rằng đây là hành vi ngoài ý muốn.

Xem xét rằng trình soạn thảo Xaml tạo ra các hàm xử lý trong lớp kiểm soát một phần của bạn và nếu lớp này không hoàn thành đang được xây dựng, nó không thể xử lý các sự kiện. Tôi không nghĩ rằng bắn một sự kiện kiểm tra cho một điều khiển thiết lập của bạn như khởi tạo để kiểm tra có vẻ đúng cả.

Ý tôi là, nó có nên kích hoạt sự kiện không được kiểm soát nếu bạn đặt trạng thái ban đầu là không được chọn không?

1

Tôi gặp vấn đề tương tự và tôi nghĩ đó là lỗi. Tuy nhiên, tôi đã tìm thấy một giải pháp thay thế: Tôi đã xóa 'Được đánh dấu' khỏi Xaml và đặt mã đó vào mã phía sau sau init

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