2010-02-13 35 views
7

Tôi đã thử một số lượng lớn các cách để có được một tham chiếu tĩnh của cửa sổ của tôi trên chương trình của tôi. Tôi cần truy cập tất cả các thành viên của nó khi chạy từ các lớp khác nhau, vì vậy cần có một tham chiếu tĩnh.Làm thế nào để có được một tham chiếu tĩnh đến một cửa sổ WPF?

Điều tôi muốn có là một cái gì đó như Program.Window1, trong đó Core là tĩnh và MyWindow là một trong các thành viên tĩnh của nó.

Trong WinForms, tôi thường khai báo biểu mẫu tĩnh của tôi trong Program.cs, nhưng điều này dường như không hoạt động với WPF và tùy chỉnh "App.xaml" ApplicationDefinition của chúng.

Tôi có thể làm như thế nào?

Lưu ý: Tôi đã thử một số cách: sử dụng lệnh gọi trực tiếp đến cửa sổ mới (ví dụ: Program.Window1 = new Window1()) sẽ không hoạt động vì tôi nhận được một số ngoại lệ về lỗi không hợp lệ. Như tôi đã hiểu cho đến nay, chỉ có ApplicationDefinitions mới có thể khởi chạy các cửa sổ trong WPF.

Dưới đây là ngoại lệ bất cứ khi nào tôi cố gắng tạo ra một cửa sổ "bởi mã" và không phải do mặc định StartupUri XAML ApplicationDefinition của:

Các thread gọi phải STA, vì nhiều thành phần giao diện người dùng yêu cầu này.

+0

Bạn phải đánh dấu Phương pháp chính bằng [STAThread] nếu bạn cần tạo cửa sổ trong mã. –

Trả lời

10

Tạo lớp tĩnh có thể chứa đối tượng cửa sổ và sau đó khi cửa sổ được tạo, nó sẽ tự chuyển đến lớp tĩnh, sau đó trên lớp tĩnh có thể phân phát đối tượng cửa sổ cho các bên quan tâm mặc dù chính đối tượng cửa sổ không tĩnh. Một cái gì đó như thế này. Không cần cho biểu mẫu của bạn tĩnh, bạn chỉ cần một nơi tĩnh để giữ đối tượng biểu mẫu.

public class Core 
{ 
    internal static MyWindowClass m_Wnd = null; 

    // call this when your non-static form is created 
    // 
    public static void SetWnd(MyWindowClass wnd) 
    { 
     m_Wnd = wnd; 
    } 

    public static MyWindow { get { return m_Wnd; } } 
} 
4

Bạn hoàn toàn có thể khởi tạo các cửa sổ của riêng mình bằng WPF. Nhưng có, bạn sẽ phải ở trên "giao diện người dùng" (đó là một chủ đề STA).

Ví dụ: giả sử rằng chúng tôi muốn có thuộc tính trên lớp Ứng dụng của chúng tôi để hiển thị một số cửa sổ.

public partial class App 
    { 
     private static Window _myWindow; 

     public static Window1 MyWindow 
     { 
      get 
      { 
       if (_myWindow == null) 
        _myWindow = new Window1(); 
       return _myWindow; 
      } 
     } 
    } 

Vấn đề với mã này là, như bạn đã có kinh nghiệm, tùy thuộc vào những gì thread được gọi getter MyWindow, new Window1() sẽ thất bại nếu các chủ đề không phải là một STA.

Để đảm bảo cửa sổ được tạo trên đúng sợi, hãy nhập the Dispatcher object. Đối tượng này được sử dụng trong suốt WPF để đảm bảo rằng giao tiếp giữa các phần tử giao diện người dùng được thực hiện trên luồng chính xác.

Về new Window1 của chúng tôi, chúng ta có thể sử dụng đối tượng App.Dispatcher để đảm bảo hoạt động new được thực hiện trên các chủ đề ứng dụng chính như sau:

 public static Window1 MyWindow 
     { 
      get 
      { 
       if (_myWindow == null) 
       { 
        var window = 
          Application.Current.Dispatcher.Invoke(
           new Func<Window1>(() => new Window1())); 

        _myWindow = (Window1)window; 
       } 

       return _myWindow; 
      } 
     } 

Ở đây, tôi được một tổ chức vào hiện tại đối tượng Điều phối viên của ứng dụng và gọi Invoke với một đại biểu thực hiện việc mới thực sự. Invoke đảm bảo rằng đại biểu của tôi được thực hiện đúng chủ đề và trả về kết quả. Thì đấy, cửa sổ được tạo ra mà không có lỗi STA đáng sợ.

Bây giờ, điều bạn phải lưu ý là các cuộc gọi tiếp tục được thực hiện trên cá thể MyWindow cũng phải được thực hiện trên chuỗi chính xác. Để tránh xả rác mã của bạn với các cuộc gọi đến Dispatcher.Gọi, nó có thể hữu ích để bọc thể hiện cửa sổ phía sau một API đơn giản. Ví dụ. một Hiện phương pháp có thể được thực hiện như thế này, đảm bảo để marshal Hiển thị cuộc gọi thông qua đối tượng Dispatcher của cửa sổ:

 public static void ShowMyWindow() 
     { 
      MyWindow.Dispatcher.Invoke(new Action(MyWindow.Show)); 
     } 
+0

Có vẻ phù hợp hơn, nhưng phương pháp trên đơn giản hơn và sẽ làm. Cảm ơn câu trả lời của bạn mặc dù. +1 – Lazlo

+0

Sau đó, nó là tốt :) Cảm ơn bạn đã bỏ phiếu! –

5

Hãy thử điều này ((MainWindow) App.Current.Windows [0]) MainCanvas..

2

Tôi đã sử dụng thành công này. Khai báo biến tĩnh của kiểu cửa sổ. Sau đó, trong hàm tạo của cửa sổ thiết lập biến tĩnh thành "this". Tôi đã sử dụng nó trong suốt các ứng dụng và nó có vẻ là làm việc tốt từ bên trong phương pháp tĩnh hoặc dụ.

public static MainWindow screenMain = null; 
    public MainWindow() 
    { 
     InitializeComponent(); 

     screenMain = this; //static reference to this. 

    } 

Ví dụ: tôi có thể thực hiện việc này.

private delegate void del(); 
    .... 
    screenMain.Dispatcher.Invoke(new del(delegate() 
    { 
     screenMain.ButtonSubmit.IsEnabled = true; 
     screenMain.ButtonPreClearing.IsEnabled = true; 
    })); 
Các vấn đề liên quan