日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

轻量级MVVM框架Stylet介绍:(11) Screen和Conductors

發(fā)布時(shí)間:2024/6/21 综合教程 59 生活家
生活随笔 收集整理的這篇文章主要介紹了 轻量级MVVM框架Stylet介绍:(11) Screen和Conductors 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

ViewModel生命周期

一個(gè)好的起點(diǎn)是查看 ViewModel 生命周期。

想象一個(gè)選項(xiàng)卡式界面 - 類似于Visual Studio,它有一個(gè)shell(包含菜單,工具欄等)和一個(gè)包含編輯器選項(xiàng)卡的TabControl。在 Stylet 中,每個(gè)編輯器選項(xiàng)卡都將由其自己的 ViewModel 提供支持。

現(xiàn)在,其中一個(gè) ViewModel 將通過實(shí)例化來開始其生命。接下來,將顯示它。之后,它可能會(huì)顯示或隱藏,具體取決于當(dāng)前處于活動(dòng)狀態(tài)的選項(xiàng)卡,然后最終關(guān)閉。在關(guān)閉之前,它有機(jī)會(huì)阻止關(guān)閉以提示您保存文件。

簡而言之,這是 ViewModel 的生命周期:它已創(chuàng)建,然后激活(顯示給用戶)。之后,它可以被停用(仍然活著但未顯示)并再次激活任意次數(shù),然后最終被關(guān)閉(在被問及它是否準(zhǔn)備好關(guān)閉之后)。

IDisposable

如果ViewModel實(shí)現(xiàn)了IDisposable,那么在其被父類關(guān)閉后將自動(dòng)釋放(除非父類的DisposeChildren的屬性為false).

Conductors介紹

現(xiàn)在,ViewModel 不會(huì)神奇地知道它何時(shí)顯示、隱藏或關(guān)閉。必須告訴它。這是指揮的角色。

簡單地說,Conductors是一個(gè)視圖模型,它擁有另一個(gè)視圖模型,并且知道如何管理其生命周期。

在我們的Visual Studio示例中,Conductor將是ViewModel,它擁有TabControl,其中顯示了編輯器ViewModels,因此可能是Shell ViewModel。每當(dāng)用戶選擇新的編輯器選項(xiàng)卡時(shí),Conductor 都會(huì)停用舊選項(xiàng)卡,并激活新選項(xiàng)卡。當(dāng)用戶關(guān)閉選項(xiàng)卡時(shí),Conductor 將告訴該選項(xiàng)卡它已關(guān)閉,然后確定要顯示的下一個(gè)選項(xiàng)卡,并激活該選項(xiàng)卡。

ViewModels 有一個(gè)生命周期,它由擁有 ViewModel 的 Conductor 實(shí)現(xiàn)。

到目前為止,這已經(jīng)非常抽象了 - 讓我們進(jìn)入細(xì)節(jié)。

IScreen和Screen

正如我們在上面看到的,ViewModel 的生命周期由該 ViewModel 上的 Conductor 調(diào)用方法進(jìn)行管理。這些方法在一組獨(dú)立的接口中定義 - 如果您實(shí)現(xiàn)了該接口,并且 ViewModel 的管理對象是 Conductor,則將調(diào)用該方法。如果需要,您可以選擇所需的接口。

有一個(gè)調(diào)用的總體接口IScreen來組成它們,還有一個(gè)名為Screen 的默認(rèn)實(shí)現(xiàn)。這表現(xiàn)得非常好,你可能永遠(yuǎn)不需要實(shí)現(xiàn)自己的。

IScreenState:用于激活、停用和關(guān)閉 ViewModel。具有Activate 、Deactivate 和 Close方法,以及用于跟蹤屏幕狀態(tài)更改的事件和屬性。
IGuardClose:用于詢問 ViewModel 是否可以關(guān)閉。有一個(gè)方法CanCloseAsync。
IViewAware:有時(shí) ViewModel 需要了解其視圖(何時(shí)附加、它是什么等)。此接口通過屬性View和方法AttachView允許這樣做。
IHaveDisplayName:有一個(gè)DisplayName屬性。這個(gè)名稱被用作使用窗口管理器顯示的窗口和對話框的標(biāo)題,對于像TabControls這樣的東西也很有用。
IChild:對于 ViewModel 來說,知道 Conductor 在管理它的是什么(例如,請求關(guān)閉它)可能是有利的。如果 ViewModel 實(shí)現(xiàn)了IChild ,它將被告知這一點(diǎn)。
請注意,無法保證調(diào)用"激活"、"停用"和"關(guān)閉"的順序 - ViewModel 可以連續(xù)激活兩次,然后關(guān)閉而不停用。由 ViewModel 來注意這些事情,并做出相應(yīng)的反應(yīng)。Stylet's Screen就是這樣做的。

Screen有一些虛擬方法,如果你愿意,我們鼓勵(lì)你覆蓋:

OnInitialActivate:第一次激活屏幕時(shí)調(diào)用,并且永遠(yuǎn)不會(huì)再調(diào)用。對于設(shè)置您不想在構(gòu)造函數(shù)中設(shè)置的內(nèi)容非常有用。
OnActivate:在屏幕激活時(shí)調(diào)用。僅當(dāng)屏幕尚未激活時(shí)才會(huì)被調(diào)用。
OnDeactivate:在屏幕停用時(shí)調(diào)用。僅當(dāng)屏幕尚未停用時(shí)才會(huì)被調(diào)用。
OnClose:在屏幕關(guān)閉時(shí)調(diào)用。只會(huì)被調(diào)用一次。僅在屏幕停用時(shí)調(diào)用。
OnViewLoaded:在觸發(fā) View 的Loaded事件時(shí)調(diào)用。
CanCloseAsync:當(dāng)Conductor想知道Screen是否可以關(guān)閉時(shí)調(diào)用,默認(rèn)情況下,返回Task.FromResult(this.CanClose).但您可以在此處添加自己的異步邏輯。
CanClose:默認(rèn)情況下調(diào)用CanCloseAsync。如果要決定是否可以同步關(guān)閉,請覆蓋CanClose 。如果要異步?jīng)Q定,請覆蓋 CanCloseAsync。
RequestClose(bool? dialogResult = null):當(dāng)您想向自己的Conductor請求關(guān)閉時(shí),您可以調(diào)用此方法。如果需要在對話框中顯示,則使用 DialogResult 參數(shù)。

Screen 派生自PropertyChangedBase,因此很容易引發(fā) PropertyChanged 通知。

您可能會(huì)發(fā)現(xiàn)所有 ViewModels 都是 Screen 的子類。這并不是說它們需要 - 您可以創(chuàng)建自己的實(shí)現(xiàn),或者從上面選擇要實(shí)現(xiàn)的接口 IScreen- 但它既方便又強(qiáng)大。

有關(guān)Conductors的詳細(xì)描述

Conductors有各種風(fēng)格,每種風(fēng)格都有自己的用例。Conductors可以擁有單個(gè) ViewModel(想想一次顯示一個(gè)頁面的導(dǎo)航),也可以擁有多個(gè) ViewModel,但一次只能有一個(gè)活動(dòng)模型(想想上面 Visual Studio 示例中的 TabControl),也可以是所有 ViewModels(想想具有大量獨(dú)立元素的網(wǎng)格)。Conductors還可以添加行為,例如保持一個(gè)顯示ViewModel的記錄(對于導(dǎo)航很有用)。

與Screen類一樣,Stylet 定義了許多Conductor感興趣的接口,以及許多實(shí)現(xiàn)(取決于所需的Conductor行為類型),盡管您當(dāng)然可以實(shí)現(xiàn)自己的接口。

主接口是 IConductor,它表示一個(gè)可供交互的Conductor。它具有以下方法

ActivateItem(T item):獲取給定的項(xiàng)目,然后將其激活。是否停用了先前的項(xiàng)目由Conductor決定。
DeactivateItem(T item):獲取給定的項(xiàng)目,然后將其停用。是否激活另一個(gè)項(xiàng)目由Conductor決定。
CloseItem(T item):取出給定的項(xiàng)目,然后將其關(guān)閉。這是否會(huì)導(dǎo)致另一個(gè)項(xiàng)目被激活以取代其位置是特定于Conductor的。

具有單個(gè)活動(dòng)項(xiàng)(無論它們可能有多少個(gè)非活動(dòng)項(xiàng))的Conductor也實(shí)現(xiàn)IHaveActiveItem ,它具有單個(gè)屬性 ActiveItem。

所有內(nèi)置Conductors都將各已經(jīng)實(shí)現(xiàn)IChild接口的item的Parent屬性設(shè)置為其身。所有內(nèi)置Conductors額外實(shí)現(xiàn)了IChildDelegate,這允許子項(xiàng)請求關(guān)閉(調(diào)用CloseItem)。默認(rèn)Screen實(shí)現(xiàn)中,調(diào)用Screen.RequestClose將會(huì)導(dǎo)致Screen在其父類上調(diào)用CloseItem(前提是其父類實(shí)現(xiàn)IChildDelegate),這反過來又會(huì)導(dǎo)致其父級(如果存在)關(guān)閉它。

內(nèi)置Conductor

Stylet內(nèi)置了一些Conductor,它們以多種直觀的方式執(zhí)行。

所有這些Condcutor都派生自Screen ,允許Conductor輕松擁有其他conductor。這意味著您可以以任何您想要的方式組成conductors和screens。

Conductor

這個(gè)非常簡單的Conductor擁有一個(gè) ViewModel(類型T),該模型公開為 ActiveItem. ActivateItem方法用于將當(dāng)前實(shí)例替換為新的 ViewModel 實(shí)例,并將激活新項(xiàng)并關(guān)閉舊項(xiàng)。每當(dāng) Conductor激活 時(shí),它就會(huì)激活其ActiveItem ;同樣,它分別在停用或關(guān)閉時(shí)停用和關(guān)閉ActiveItem。

當(dāng)被問及是否可以關(guān)閉它(當(dāng)CanCloseAsync被調(diào)用時(shí))時(shí),它會(huì)返回ActiveItem返回的任何內(nèi)容,如果沒有ActiveItem, 則返回 true。

也可以直接設(shè)置ActiveItem,這與調(diào)用ActivateItem具有相同的效果。

Conductor的 ViewModel 如下所示 - 綁定了到Conductor的 ActiveItem 屬性的ContentControl:

<Window x:Class="MyNamespace.ConductorViewModel"
        xmlns:s="https://github.com/canton7/Stylet" ....>
   <ContentControl s:View.Model="{Binding ActiveItem}"/>
</Window>

Conductor.Collection.OneActive

該Conductor擁有許多items,但一次只能有一個(gè)item處于活動(dòng)狀態(tài)。通過這種方式,它可以對 TabControl 的行為進(jìn)行建模 - 許多選項(xiàng)卡可以同時(shí)存在,但一次只能顯示一個(gè)選項(xiàng)卡。

它擁有一個(gè)T類型的item的集合,其中一個(gè)被設(shè)置為ActiveItem。調(diào)用ActivateItem將添加的item傳遞到集合的Items,并且還會(huì)激活它并將其設(shè)置為ActiveItem ;如果之前設(shè)置了ActiveItem,則其舊值將被停用,并保留在集合中。

調(diào)用DeactivateItem或CloseItem某個(gè)項(xiàng)目將分別導(dǎo)致該項(xiàng)目被停用和關(guān)閉。由于它不再處于活動(dòng)狀態(tài),因此不能保持為ActiveItem - 而是選擇另一個(gè)項(xiàng)目作為 ActiveItem,并被激活并按此方式設(shè)置。默認(rèn)情況下,新的ActiveItem位于集合Items中要停用/關(guān)閉的項(xiàng)前面。

如果需要,可以直接操作集合Items。也可以直接設(shè)置ActiveItem,這與調(diào)用ActivateItem具有相同的效果。

帶有使用此Conductor的 TabControl 的 ViewModel 可能如下所示(有關(guān)簡短版本,請參見下文):

<TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding ActiveItem}" DisplayMemberPath="DisplayName">
   <TabControl.ContentTemplate>
      <DataTemplate>
         <ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False"/>
      </DataTemplate>
   </TabControl.ContentTemplate>
</TabControl>

除了以上風(fēng)格以外,Stylet還提供了一種可以做同樣的事情的風(fēng)格。這意味著您可以改為執(zhí)行以下操作:

<TabControl Style="{StaticResource StyletConductorTabControl}"/>

Conductor.Collection.AllActive

這個(gè)Conductor與Conductor.Collection.OneActive非常相似,只是它沒有一個(gè)ActiveItem 。相反,它只有Item的集合。激活項(xiàng)目(使用 ActivateItem)后,該項(xiàng)目將添加到此集合中,關(guān)閉后,該項(xiàng)目將從此集合中刪除。

調(diào)用DeactivateItem將就地停用該項(xiàng)目,而不會(huì)將其從集合Items中刪除。

也可以直接操作集合Items。添加的任何項(xiàng)目都將被激活,任何已刪除的項(xiàng)目都將被關(guān)閉。

典型的用例可能是使用 ItemsControl,其中所有項(xiàng)同時(shí)可見。以這種方式使用 ItemsControl 的 ViewModel 可能如下所示(同樣,有關(guān)簡短版本,請參閱下面的內(nèi)容):

<ItemsControl ItemsSource="{Binding Items}">
   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False"/>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

由于這非常冗長,Stylet 提供了一種樣式,用于設(shè)置以下屬性:

<ItemsControl Style="{StaticResource StyletConductorItemsControl}"/>

Conductor.StackNavigation

這個(gè)Conductor是 Conductor和Conductor.Collection.OneActive 之間的混合體,它提供了一些額外的東西:基于堆棧的導(dǎo)航。

它有一個(gè)單一的ActiveItem,但也保留了過去活動(dòng)的項(xiàng)目的(私有的)歷史記錄。激活新項(xiàng)目時(shí),將停用前一個(gè)ActiveItem,并將其推送到歷史記錄堆棧。調(diào)用GoBack()將關(guān)閉當(dāng)前ActiveItem ,并重新激活此歷史記錄堆棧中的頂部項(xiàng)目,并將其設(shè)置為新的 ActiveItem。

如果對當(dāng)前ActiveItem調(diào)用CloseItem,則具有相同的效果。如果調(diào)用歷史記錄堆棧中存在的任何項(xiàng)目,則該項(xiàng)目將被關(guān)閉并從歷史記錄堆棧中刪除。調(diào)用Clear()將關(guān)閉并從歷史記錄堆棧中刪除所有項(xiàng)目。

WindowConductor

這個(gè)有點(diǎn)奇怪,因?yàn)樗莾?nèi)部的,你不需要直接與它互動(dòng),但為了引起興趣,我把它包括在這里。每當(dāng)您使用WindowManager 顯示對話框或窗口時(shí)(這包括 Stylet 首次啟動(dòng)應(yīng)用程序時(shí)顯示的窗口)時(shí),都會(huì)有一個(gè)新的WindowConductor來管理其生命周期。每當(dāng)窗口或?qū)υ捒蜃钚』瘯r(shí),它都會(huì)被停用。每當(dāng)它被最大化時(shí),它就會(huì)被激活。如果您的 ViewModel 請求關(guān)閉它(見上文RequestClose),則WindowConductor會(huì)處理此問題。同樣,如果用戶自己關(guān)閉窗口,WindowConductor則會(huì)詢問您的 ViewModel 它是否已準(zhǔn)備好關(guān)閉。

總結(jié)

以上是生活随笔為你收集整理的轻量级MVVM框架Stylet介绍:(11) Screen和Conductors的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。