視圖模型管理
本文描述了如何在運行時檢索ViewModel實例,注意如果您在設計時使用MvvmContext組件來構建 MVVM-applications,該組件將自動管理ViewModels。
如果ViewModel遵循POCO概念,MVVM框架將動態(tài)地把該ViewModel轉換為包含必要基礎結構(例如,支持簡化的)的新類。框架與動態(tài)創(chuàng)建的類實例一起工作,這意味著您無法在運行時初始訪問這些實例,因為它們的類型尚未確定。
使用以下選項來檢索工作的ViewMode:
- The ViewModelSource.Create method
在這種方法中,您首先創(chuàng)建一個ViewModel實例,然后調用SetViewModel方法將該實例與特定的ViewModel類型關聯(lián)起來。
C#:
var mainViewModel = ViewModelSource.Create<MainViewModel>(); mvvmContext1.SetViewModel(typeof(MainViewModel), mainViewModel);
VB.NET:
Dim mainViewModel = ViewModelSource.Create(Of MainViewModel)() mvvmContext1.SetViewModel(GetType(MainViewModel), mainViewModel)
- The ViewModelBase class
您可以從實現(xiàn)MVVM框架特性的ViewModelBase類中繼承ViewModels,在這種情況下,是可以直接創(chuàng)建ViewModel實例。注意,此時還需調用SetViewModel方法來指定框架在需要ViewModel時應該使用這個實例。
C#:
public class ViewModel : ViewModelBase {
//. . .
}
var myViewModel = new ViewModel();
mvvmContext1.SetViewModel(typeof(ViewModel), myViewModel);
VB.NET:
Public Class ViewModel Inherits ViewModelBase '. . . End Class Private myViewModel = New ViewModel() mvvmContext1.SetViewModel(GetType(ViewModel), myViewModel)
我們不推薦這種方法,因為您將失去POCO模型提供的所有特性。
- ViewModelCreate events
這種方法被設計為與依賴注入框架(如)一起工作,下面的例子說明了這種注入是如何與Ninject 框架一起工作的。
C#:
public class SamuraiViewModel {
public IWeapon Weapon { get; private set; }
public SamuraiViewModel(IWeapon weapon) {
this.Weapon = weapon;
}
public void Attack() {
Weapon.Hit();
}
}
// Bind a dependency for IWeapon
kernel.Bind<IWeapon>().To<Sword>();
// Set up MVVMContext
var fluent = mvvmContext1.OfType<SamuraiViewModel>();
fluent.BindCommand(simpleButton1, x => x.Attack());
VB.NET:
Public Class SamuraiViewModel Private privateWeapon As IWeapon Public Property Weapon() As IWeapon Get Return privateWeapon End Get Private Set(ByVal value As IWeapon) privateWeapon = value End Set End Property Public Sub New(ByVal weapon As IWeapon) Me.Weapon = weapon End Sub Public Sub Attack() Weapon.Hit() End Sub End Class ' Bind a dependency for IWeapon kernel.Bind(Of IWeapon)().To(Of Sword)() ' Set up MVVMContext Dim fluent = mvvmContext1.OfType(Of SamuraiViewModel)() fluent.BindCommand(simpleButton1, Function(x) x.Attack())
在這種情況下,您需要動態(tài)生成Viewmodel并將它們綁定到接口(當將接口直接綁定到POCO時,MVVM框架特性將丟失)。要獲得所需的實例,處理常規(guī)(本地)或靜態(tài)(全局)ViewModelCreate事件如下:
C#:
// Retrieve the live POCO ViewModel instance with the Ninject kernel
//regular event
mvvmContext1.ViewModelCreate += MVVMContext_ViewModelCreate;
void MVVMContext_ViewModelCreate(object sender, DevExpress.Utils.MVVM.ViewModelCreateEventArgs e) {
// kernel.Bind<SamuraiViewModel>().To(e.RuntimeViewModelType);
// e.ViewModel = kernel.Get<SamuraiViewModel>();
e.ViewModel = kernel.Get(e.RuntimeViewModelType);
}
//static event
MVVMContextCompositionRoot.ViewModelCreate += (s,e)=> {
e.ViewModel = kernel.Get(e.RuntimeViewModelType);
};
VB.NET:
' Retrieve the live POCO ViewModel instance with the Ninject kernel 'regular event AddHandler mvvmContext1.ViewModelCreate, AddressOf MVVMContext_ViewModelCreate void MVVMContext_ViewModelCreate(Object sender, DevExpress.Utils.MVVM.ViewModelCreateEventArgs e) ' kernel.Bind<SamuraiViewModel>().To(e.RuntimeViewModelType); ' e.ViewModel = kernel.Get<SamuraiViewModel>(); e.ViewModel = kernel.Get(e.RuntimeViewModelType) 'static event AddHandler MVVMContextCompositionRoot.ViewModelCreate, Sub(s,e) e.ViewModel = kernel.Get(e.RuntimeViewModelType)
靜態(tài)ViewModelCreate事件是一個weak event,如果它包含一個變量的閉包(上面示例中的" kernel "或下面示例中的" rootContainer "范圍),其生命周期短于父容器的生命周期,那么VS垃圾收集器可能會過早地收集該變量,并且事件處理程序可能永遠不會被調用。
C#:
[STAThread]
static void Main() {
//rootContainer is declared at the Main method level
IContainer rootContainer;
var builder = new ContainerBuilder();
builder.RegisterType<TestViewModel>();
builder.RegisterType<MyClass>().As<IService>();
rootContainer = builder.Build();
MVVMContextCompositionRoot.ViewModelCreate += (s, e) => {
using (var scope = rootContainer.BeginLifetimeScope(
b => b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType))) {
e.ViewModel = scope.Resolve(e.ViewModelType);
}
};
}
VB.NET:
<STAThread> Shared Sub Main() 'rootContainer is declared at the Main method level Dim rootContainer As IContainer Dim builder = New ContainerBuilder() builder.RegisterType(Of TestViewModel)() builder.RegisterType(Of [MyClass])().As(Of IService)() rootContainer = builder.Build() AddHandler MVVMContextCompositionRoot.ViewModelCreate, Sub(s, e) Using scope = rootContainer.BeginLifetimeScope(Function(b) b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType)) e.ViewModel = scope.Resolve(e.ViewModelType) End Using End Sub End Sub
要解決潛在的問題,請在執(zhí)行訂閱的對象級別將變量聲明為屬性/字段。
C#:
//rootContainer is declared at the root level
private static IContainer rootContainer { get; set; }
[STAThread]
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestViewModel>();
builder.RegisterType<MyClass>().As<IService>();
rootContainer = builder.Build();
MVVMContextCompositionRoot.ViewModelCreate += (s, e) =>
{
using (var scope = rootContainer.BeginLifetimeScope(
b => b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType))) {
e.ViewModel = scope.Resolve(e.ViewModelType);
}
};
}
VB.NET:
'rootContainer is declared at the root level Private Shared Property rootContainer() As IContainer <STAThread> Shared Sub Main() Dim builder = New ContainerBuilder() builder.RegisterType(Of TestViewModel)() builder.RegisterType(Of [MyClass])().As(Of IService)() rootContainer = builder.Build() AddHandler MVVMContextCompositionRoot.ViewModelCreate, Sub(s, e) Using scope = rootContainer.BeginLifetimeScope(Function(b) b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType)) e.ViewModel = scope.Resolve(e.ViewModelType) End Using End Sub End Sub

 QQ交談
QQ交談 在線咨詢
在線咨詢 
                 
                
 渝公網(wǎng)安備
            50010702500608號
渝公網(wǎng)安備
            50010702500608號
             
            
 客服熱線
客服熱線