public class ViewModel : BindableBase { public string FirstName { get { return GetValue<string>(); } set { SetValue(value); } } } public class ViewModel : BindableBase { public string FirstName { get { return GetValue<string>(); } set { SetValue(value, changedCallback: NotifyFullNameChanged); } } public string LastName { get { return GetValue<string>(); } set { SetValue(value, changedCallback: NotifyFullNameChanged); } } public string FullName { get { return FirstName + " " + LastName; } } void NotifyFullNameChanged() { RaisePropertyChanged(nameof(FullName)); } }
ViewModelBase class provides the OnInitializeInDesignMode and OnInitializeInRuntime protected virtual methods, which you can override to initialize properties for runtime and design time modes separately.
public class ViewModel : ViewModelBase { protected override void OnInitializeInDesignMode() { base.OnInitializeInDesignMode(); Employees = new List<Employee>() { new Employee() { Name = "Employee 1" }, }; } protected override void OnInitializeInRuntime() { base.OnInitializeInRuntime(); Employees = DatabaseController.GetEmployees(); } }
The ViewModelBase class implements the ISupportServices interface that maintains the Services mechanism. The ViewModelBase.GetService method, which employs ISupportServices interface, allows you to access services registered in a View.
<UserControl x:Class="ViewModelBaseSample.View" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModels="clr-namespace:ViewModelBaseSample.ViewModels" ...> <UserControl.DataContext> <ViewModels:ViewModel/> </UserControl.DataContext> <dxmvvm:Interaction.Behaviors> <dxmvvm:MessageBoxService/> </dxmvvm:Interaction.Behaviors> ... </UserControl>
public class ViewModel : ViewModelBase { public IMessageBoxService MessageBoxService { get { return GetService<IMessageBoxService>(); } } }
If it is necessary to use several services of the same type, assign the Name property for these services and access a specific service by its name.
<dxmvvm:Interaction.Behaviors> <dx:DXMessageBoxService x:Name="service1"/> <dx:DXMessageBoxService x:Name="service2"/> </dxmvvm:Interaction.Behaviors> public IMessageBoxService MessageBoxService1 { get { return GetService<IMessageBoxService>("service1"); } } public IMessageBoxService MessageBoxService2 { get { return GetService<IMessageBoxService>("service2"); } }
View Models inherited from the ViewModelBase can be related to each other with a parent-child relationship. This is achieved with the ISupportParentViewModel interface that is implemented in the ViewModelBase class. In this case, child View Models may access Services registered in the main View Model.
public class DetailViewModel : ViewModelBase { public IMessageBoxService MessageBoxService { get { return GetService<IMessageBoxService>(); } } } public class MainViewModel : ViewModelBase { public IMessageBoxService MessageBoxService { get { return GetService<IMessageBoxService>(); } } public DetailViewModel DetailViewModel { get; private set; } public MainViewModel() { DetailViewModel = new DetailViewModel(); ((ISupportParentViewModel)DetailViewModel).ParentViewModel = this; } }
或者
<Grid x:Name="LayoutRoot"> ... <!-- It is necessary to use the ElementName binding mode, because the DetailView‘s DataContext is a DetailViewModel object. That is why the following regular binding cannot be used in this case: dxmvvm:ViewModelExtensions.Parameter="{Binding}" Instead, use one of the following constructions:--> <View:DetailView dxmvvm:ViewModelExtensions.ParentViewModel="{Binding DataContext, ElementName=LayoutRoot}"/> <ContentControl> <ContentControl.ContentTemplate> <DataTemplate> <View:DetailView dxmvvm:ViewModelExtensions.ParentViewModel="{Binding DataContext, Source={x:Reference LayoutRoot}}"/> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> ... </Grid>
ViewModelBase class implements the ISupportParameter interface, which can be used for passing initial data to View Models.
public class MainViewModel : ViewModelBase { public DetailViewModel DetailViewModel { get; private set; } public MainViewModel() { DetailViewModel = new DetailViewModel(); ((ISupportParameter)DetailViewModel).Parameter = "Document 1"; } }
When the Parameter property is set, the ViewModelBase.OnParameterChanged virtual method is invoked. You can override the ViewModelBase.OnParameterChanged virtual method to process passed data.
public class DetailViewModel : ViewModelBase { protected override void OnParameterChanged(object parameter) { base.OnParameterChanged(parameter); if(IsInDesignMode) { //... } else { //... } } }
when View Models do not know about each other. In this case, you should set the ViewModelExtensions.Parameter attached property in XAML.
<Grid x:Name="LayoutRoot"> ... <!-- It is necessary to use the ElementName binding mode, because the DetailView‘s DataContext is a DetailViewModel object. That is why the following regular binding cannot be used in this case: dxmvvm:ViewModelExtensions.Parameter="{Binding}" Instead, use one of the following constructions:--> <View:DetailView dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext, ElementName=LayoutRoot}"/> <ContentControl> <ContentControl.ContentTemplate> <DataTemplate> <View:DetailView dxmvvm:ViewModelExtensions.Parameter="{Binding DataContext, Source={x:Reference LayoutRoot}}"/> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> ... </Grid>
The ViewModelBase class implements the ICustomTypeDescriptor interface to provide the capability to automatically create command properties based on methods (with the Command attribute) at runtime.
<Button Command="{Binding SaveCommand}"/> public class ViewModel : ViewModelBase { [Command] public void Save() { //... } public bool CanSave() { //... } }
原文:https://www.cnblogs.com/yetsen/p/13767982.html