簡體   English   中英

WPF Caliburn.Micro - 在Singe Window應用程序中導航的最佳方式

[英]WPF Caliburn.Micro - Best way to navigate in Singe Window Application

  1. 我的歷史:

我正在開發一個WPF應用程序,它將在觸摸屏上全屏運行。 我的應用程序中的導航只能通過單擊每個頁面上的按鈕(“后退”或“注銷”)來完成。

這不是通用應用程序,但它看起來像。

  1. 項目假設:

    • 應用程序將在觸摸屏上的Windows 7中以全屏模式運行。
    • 我正在使用Caliburn.Micro MVVM框架。
  2. 問題和疑問:

我有一個窗口和3個UserControl(和ViewModels) 概念藝術

 Window ShellView
     UserControl LoginView
     UserControl OrdersView
     UserControl OrderDetailView

當應用程序啟動時,我將LoginView設置為默認值並使用CM Conductor ActivateItem方法加載它,但我不知道如何從UserControl設置另一個View,如LoginView

我讀過: 這個問題,但這不包括我的案例和答案,但這對我來說很難理解。

我的想法:

  • 在ShellViewModel中創建靜態方法,如:

ShellViewModel

public static void setOrdersView() {
    ActivateItem(new OrdersViewModel());
    // Error : An object reference is required for the non-static field, method, or property 'Caliburn.Micro.ConductorBase<object>.ActivateItem(object)
}
ShellViewModel.setOrdersView();
  • 在ShellViewModel中創建監聽器並從子ViewModel發送事件(但現在我不知道如何實現它)

問題:在這種情況下,處理導航的最佳方法是什么?

  1. 應用架構:

ShellView

<Window>
   <ContentControl x:Name="ActiveItem" />
</Window>

ShellViewModel

public class ShellViewModel : Conductor<object>, IShell
{

    public ShellViewModel()
    {
        LoadDefault();
    }    

    public void LoadDefault()
    {
        ActivateItem(new LoginViewModel());
    }
}

LoginView

<UserControl>
    <Button x:Name="Login" />
</UserControl>

LoginViewModel

public class LoginViewModel : PropertyChangedBase
{
    public void Login() {
        if (LoginManager.Login("User", "Password")) {
            // How to redirect user to OrdersView?
        }
    }
}

我有類似的應用程序,一個shell窗口和許多激活的視圖內部和一些對話框窗口。 您應該使用EventAggregator模式滿足這些需求,Caliburn已經實現了。

如何實現

最小Shell簽名

public class ShellViewModel : Conductor<object>,
    IHandle<ChangePageMessage>,
    IHandle<OpenWindowMessage>

你需要兩個字段(第二個用於對話框):

public IEventAggregator EventAggregator { get; private set; }
public IWindowManager WindowManager { get; private set; }

我通過IoC設置了這些對象的單個實例。 您也可以將它們定義為單身人士。 EventAggregator需要在實現IHandle的對象上進行訂閱。

EventAggregator.Subscribe(this); //You should Unsubscribe when message handling is no longer needed

處理程序實現:

public void Handle(ChangePageMessage message) {
    var instance = IoC.GetInstance(message.ViewModelType, null);//Or just create viewModel by type
    ActivateItem(instance);
}

public void Handle(OpenWindowMessage message) {
    var instance = IoC.GetInstance(message.ViewModelType, null);//Or just create viewModel by type
    WindowManager.ShowWindow(instance);
}

事件聚合器的消息只能是標記類,但有時傳遞更多參數(如我們的OpenWindowMessageChangePageMessage類)很有用 - 它們與內容完全相似,例如:

public class OpenWindowMessage {

    public readonly Type ViewModelType;

    public OpenWindowMessage(Type viewModelType) {
        ViewModelType = viewModelType;
    }
}

您的所有viewModel也可以訂閱EventAggregator實例並處理一些消息以進行通信,甚至是初始參數。 我幾乎為每個viewModel都有類似MyViewModelInitMessage類的東西,並且只使用兩個發布方法。

EventAggregator.Publish(new ChangePageMessage(typeof(MyViewModel)));
EventAggregator.Publish(new MyViewModelInitMessage("...all needed parameters"));

因此,當我發布這兩個 - 我的ViewModel將被激活,然后它訂閱EventAggregator不要忘記這樣做或第二個消息處理永遠不會發生 ),並將在之后處理它的InitMessage

現在使用EventAggregator,您可以在當前訂閱它的所有ViewModel之間發送消息。

這似乎很常見的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM