翻译|使用教程|编辑:龚雪|2021-11-15 10:03:21.883|阅读 213 次
概述:DevExpress WinForm创建的应用程序可利用MVVM设计模式,本文主要为大家介绍这其中的第三种属性依赖,欢迎下载最新版体验!
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
相关链接:
根据您绑定的属性,存在以下三种可能的情况:
获取工具下载 - DevExpress WinForm v21.2
属性依赖是来自同一个ViewModel的两个属性之间的关系,当一个属性发生变化时,另一个属性会更新其值。
在“MVVM 最佳实践”演示中,多个模块演示了以下设置:
对于使用示例 UI 的每个演示模块,将 View 元素绑定到 ViewModel 属性的代码都是相同的。
C#
mvvmContext.ViewModelType = typeof(MultViewModel); var fluentAPI = mvvmContext.OfType<MultViewModel>(); fluentAPI.SetBinding(editor1, e => e.EditValue, x => x.Operand1); fluentAPI.SetBinding(editor2, e => e.EditValue, x => x.Operand2); fluentAPI.SetBinding(resultLabel, l => l.Text, x => x.ResultText);
VB.NET
mvvmContext.ViewModelType = GetType(MultViewModel) Dim fluentAPI = mvvmContext.OfType(Of MultViewModel)() fluentAPI.SetBinding(editor1, Sub(e) e.EditValue, Sub(x) x.Operand1) fluentAPI.SetBinding(editor2, Sub(e) e.EditValue, Sub(x) x.Operand2) fluentAPI.SetBinding(resultLabel, Sub(l) l.Text, Sub(x) x.ResultText)
然而,属性依赖在每个模块中的声明都不同。
OnPropertyChanged 方法
在POCO ViewModels中,您可以声明OnXChanged方法,其中 X 是属性名称。 当相关属性的值发生变化时,框架会调用这些方法。
C#
public class MultViewModel { public virtual int Operand1 { get; set; } public virtual int Operand2 { get; set; } public virtual int Result { get; set; } public virtual string ResultText { get; set; } protected void OnOperand1Changed() { UpdateResult(); } protected void OnOperand2Changed() { UpdateResult(); } protected void OnResultChanged() { UpdateResultText(); } void UpdateResult() { Result = Operand1 * Operand2; } void UpdateResultText() { ResultText = string.Format("The result is: {0:n0}", Result); } }
VB.NET
Public Class MultViewModel Public Overridable Property Operand1() As Integer Public Overridable Property Operand2() As Integer Public Overridable Property Result() As Integer Public Overridable Property ResultText() As String Protected Sub OnOperand1Changed() UpdateResult() End Sub Protected Sub OnOperand2Changed() UpdateResult() End Sub Protected Sub OnResultChanged() UpdateResultText() End Sub Private Sub UpdateResult() Result = Operand1 * Operand2 End Sub Private Sub UpdateResultText() ResultText = String.Format("The result is: {0:n0}", Result) End Sub End Class
自定义更新方法
如果您的更新方法未被称为“On...Changed”,请使用 DevExpress.Mvvm.DataAnnotations.BindableProperty 属性告诉框架它应该在属性值更改时调用此方法。 在下面的代码示例中,DevExpress.Mvvm.POCO.RaisePropertyChanged 是一个 DevExpress 扩展方法,它将更新通知发送到依赖属性。
C#
public class SumViewModel { [BindableProperty(OnPropertyChangedMethodName = "NotifyResultAndResultTextChanged")] public virtual int Operand1 { get; set; } [BindableProperty(OnPropertyChangedMethodName = "NotifyResultAndResultTextChanged")] public virtual int Operand2 { get; set; } public int Result { get { return Operand1 + Operand2; } } public string ResultText { get { return string.Format("The result is: {0:n0}", Result); } } protected void NotifyResultAndResultTextChanged() { this.RaisePropertyChanged(x => x.Result); this.RaisePropertyChanged(x => x.ResultText); } }
VB.NET
Public Class SumViewModel <BindableProperty(OnPropertyChangedMethodName := "NotifyResultAndResultTextChanged")> Public Overridable Property Operand1() As Integer <BindableProperty(OnPropertyChangedMethodName := "NotifyResultAndResultTextChanged")> Public Overridable Property Operand2() As Integer Public ReadOnly Property Result() As Integer Get Return Operand1 + Operand2 End Get End Property Public ReadOnly Property ResultText() As String Get Return String.Format("The result is: {0:n0}", Result) End Get End Property Protected Sub NotifyResultAndResultTextChanged() Me.RaisePropertyChanged(Function(x) x.Result) Me.RaisePropertyChanged(Function(x) x.ResultText) End Sub End Class
依赖属性
使用 DevExpress.Mvvm.DataAnnotations.DependsOnProperties 属性标记依赖属性。 请注意,与前面的示例不同,下面的代码仅使用一个依赖项:“ResultText”取决于两个“Operand”属性,您不能使用此属性创建链式依赖项。
C#
public class MultViewModelEx { public virtual int Operand1 { get; set; } public virtual int Operand2 { get; set; } [DependsOnProperties("Operand1", "Operand2")] public string ResultText { get { return string.Format("The result is: {0:n0}", Operand1 * Operand2); } } }
VB.NET
Public Class MultViewModelEx Public Overridable Property Operand1() As Integer Public Overridable Property Operand2() As Integer <DependsOnProperties("Operand1", "Operand2")> Public ReadOnly Property ResultText() As String Get Return String.Format("The result is: {0:n0}", Operand1 * Operand2) End Get End Property End Class
Metadata类
在这种方法中,您创建自定义更新方法并使用单独的元数据类将属性与这些方法链接起来。 如果 BindableProperty 属性按名称引用更新方法,则 OnPropertyChangedCall 方法使用 lambda 表达式来检索方法。 重命名自定义更新方法时,元数据类显示编译错误。
C#
//View Model code [System.ComponentModel.DataAnnotations.MetadataType(typeof(Metadata))] public class SumViewModel_MetaPOCO { public virtual int Operand1 { get; set; } public virtual int Operand2 { get; set; } public virtual int Result { get; set; } public string ResultText { get { return string.Format("The result is: {0:n0}", Result); } } protected void NotifyResultAndResultTextChanged() { Result = Operand1 + Operand2; this.RaisePropertyChanged(x => x.Result); this.RaisePropertyChanged(x => x.ResultText); } //Metadata class public class Metadata : IMetadataProvider<SumViewModel_MetaPOCO> { void IMetadataProvider<SumViewModel_MetaPOCO>.BuildMetadata(MetadataBuilder<SumViewModel_MetaPOCO> builder) { builder.Property(x => x.Result) .DoNotMakeBindable(); builder.Property(x => x.Operand1). OnPropertyChangedCall(x => x.NotifyResultAndResultTextChanged()); builder.Property(x => x.Operand2). OnPropertyChangedCall(x => x.NotifyResultAndResultTextChanged()); } } }
VB.NET
<System.ComponentModel.DataAnnotations.MetadataType(GetType(Metadata))> Public Class SumViewModel_MetaPOCO Public Overridable Property Operand1() As Integer Public Overridable Property Operand2() As Integer Public Overridable Property Result() As Integer Public ReadOnly Property ResultText() As String Get Return String.Format("The result is: {0:n0}", Result) End Get End Property Protected Sub NotifyResultAndResultTextChanged() Result = Operand1 + Operand2 Me.RaisePropertyChanged(Function(x) x.Result) Me.RaisePropertyChanged(Function(x) x.ResultText) End Sub 'Metadata class Public Class Metadata Implements IMetadataProvider(Of SumViewModel_MetaPOCO) Private Sub IMetadataProviderGeneric_BuildMetadata(ByVal builder As MetadataBuilder(Of SumViewModel_MetaPOCO)) Implements IMetadataProvider(Of SumViewModel_MetaPOCO).BuildMetadata builder.Property(Function(x) x.Result).DoNotMakeBindable() builder.Property(Function(x) x.Operand1).OnPropertyChangedCall(Function(x) x.NotifyResultAndResultTextChanged()) builder.Property(Function(x) x.Operand2).OnPropertyChangedCall(Function(x) x.NotifyResultAndResultTextChanged()) End Sub End Class End Class
集合绑定
要使用数据源记录填充多项目控件,请使用 SetItemsSourceBinding 方法。
C#
var fluentApi = mvvmContext1.OfType<ViewModelClass>(); fluentApi.SetItemsSourceBinding( Target ItemSelector, SourceSelector, MatchExpression, CreateExpression, DisposeExpression, ChangeExpression );
VB.NET
Dim fluentApi = mvvmContext1.OfType(Of ViewModelClass)() fluentApi.SetItemsSourceBinding(Target ItemSelector, SourceSelector, MatchExpression, CreateExpression, DisposeExpression, ChangeExpression)
在 MVVM 最佳实践演示中,以下代码使用自定义实体类的对象填充列表框。 SetBinding 方法将编辑器的 SelectedItem 属性与检索相应实体对象的 ViewModel SelectedEntity 属性绑定。
C#
//View code mvvmContext.ViewModelType = typeof(ViewModel); var fluentApi = mvvmContext.OfType<ViewModel>(); fluentApi.SetItemsSourceBinding( listBox, lb => lb.Items, x => x.Entities, (item, entity) => object.Equals(item.Value, entity), entity => new ImageListBoxItem(entity), null, (item, entity) => { ((ImageListBoxItem)item).Description = entity.Text; } ); fluentApi.SetBinding(listBox, lb => lb.SelectedValue, x => x.SelectedEntity); //ViewModel code public class ViewModel { public virtual Entity SelectedEntity { get; set; } public virtual ObservableCollection<Entity> Entities { get; set;} protected void OnSelectedEntityChanged() { //"Remove" is a custom ViewModel method that deletes a selected entity this.RaiseCanExecuteChanged(x => x.Remove()); } protected void OnEntitiesChanged() { SelectedEntity = Entities.FirstOrDefault(); } } //Model code public class Entity { public Entity(int id) { this.ID = id; this.Text = "Entity " + id.ToString(); } public int ID { get; private set; } public string Text { get; set; } }
VB.NET
'View code mvvmContext.ViewModelType = GetType(ViewModel) Dim fluentApi = mvvmContext.OfType(Of ViewModel)() fluentApi.SetItemsSourceBinding( listBox, Function(lb) lb.Items, Function(x) x.Entities, Function(item, entity) Object.Equals(item.Value, entity), Function(entity) New ImageListBoxItem(entity), Nothing, Function(item, entity) CType(item, ImageListBoxItem).Description = entity.Text ) fluentApi.SetBinding(listBox, Function(lb) lb.SelectedValue, Function(x) x.SelectedEntity) 'ViewModel code Public Class ViewModel Public Overridable Property SelectedEntity() As Entity Public Overridable Property Entities() As ObservableCollection(Of Entity) Protected Sub OnSelectedEntityChanged() '"Remove" is a custom ViewModel method that deletes a selected entity Me.RaiseCanExecuteChanged(Function(x) x.Remove()) End Sub Protected Sub OnEntitiesChanged() SelectedEntity = Entities.FirstOrDefault() End Sub End Class 'Model code Public Class Entity Public Sub New(ByVal id As Integer) Me.ID = id Me.Text = "Entity " & id.ToString() End Sub Private privateID As Integer Public Property ID() As Integer Get Return privateID End Get Private Set(ByVal value As Integer) privateID = value End Set End Property Public Property Text() As String End Class
触发器
触发器允许您在 ViewModel 属性更改时修改 UI(视图)。 在 DevExpress 演示中,复选框绑定到 ViewModel “IsActive”属性。 当此属性的值更改时,触发器会更改 UI 元素(标签)的背景颜色。
C#
//ViewModel code public class ViewModel { public virtual bool IsActive { get; set; } } //ViewModel code var fluent = mvvmContext.OfType<ViewModel>(); fluent.SetBinding(checkEdit, c => c.Checked, x => x.IsActive); fluent.SetTrigger(x => x.IsActive, (active) => { if(active) label.Appearance.BackColor = Color.LightPink; else label.Appearance.BackColor = Color.Empty; });
VB.NET
'ViewModel code Public Class ViewModel Public Overridable Property IsActive() As Boolean End Class 'ViewModel code Private fluent = mvvmContext.OfType(Of ViewModel)() fluent.SetBinding(checkEdit, Function(c) c.Checked, Function(x) x.IsActive) fluent.SetTrigger(Function(x) x.IsActive, Sub(active) If active Then label.Appearance.BackColor = Color.LightPink Else label.Appearance.BackColor = Color.Empty End If End Sub)
DevExpress WinForm拥有180+组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!
更多产品正版授权详情及优惠,欢迎咨询
DevExpress技术交流群5:742234706 欢迎一起进群讨论
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自:慧都网