Current filter:
                                You should refresh the page.
                                  • This KB Article is intended for XAF developers who want to migrate their applications from the version 9.3 to the version 10.1.
                                    In this version, there a lot of changes in the application model structure have been made to improve the overall performance and usability. These guidelines will help you keep the migration process as smooth as possible.

                                    IMPORTANT NOTES
                                    1. Before migrating an existing XAF solution to version 10.1 it's strongly recommended that you make several backups.

                                    2. Before migrating an existing XAF solution to version 10.1 it's also necessary to upgrade your existing projects to version 9.3, and achieve a fully compilable solution without any warnings.
                                    During work on the new application model certain methods and properties were removed or moved to another classes.
                                    You can find information about most breaking changes in the What's New document.
                                    Take special note that it usually contains information about changes with the public and documented classes. So, some changes in internal classes cannot be listed there.
                                    We also provide a detailed guide about breaking changes not related to the application model: eXpressApp Framework v10.1 Breaking Changes & Obsoletes Migration Guidelines

                                    3. Once you accomplished this, you should open all your XAFML files in the Model Editor and save the application model customizations in version 9.3. In order to do this, it's enough to execute the 'Update Model' in the context menu invoked for a XAF project in the Solution Explorer in Visual Studio. Another way is to open the Model Editor, modify any element and save the changes.
                                    This is important because since version 10.1 all the old (prior 9.3) model difference converters are removed.

                                    4. For general information about the new application model structure and its integration with the DC technology, check out these blog posts:
                                    http://community.devexpress.com/blogs/garyshort/archive/2010/02/08/xaf-10-1-sneak-peak.aspx
                                    http://community.devexpress.com/blogs/garyshort/archive/2010/04/13/xaf-application-model-and-model-editor-improvements-v2010-vol1.aspx
                                    http://community.devexpress.com/blogs/garyshort/archive/2010/04/06/xaf-sneak-peek-domain-components.aspx

                                    5. Let us know in case of any questions regarding migration to the new application model which are not covered by this migration guide. We will be glad to help you and improve this document.

                                1 Solution

                                Creation Date Importance Sort by

                                =========================================
                                1. Extending the application model.
                                To extend the application model, you should define corresponding model interfaces, supporting the base IModelNode interface.
                                Previously, it could be done in either an xml file (for example Schema.xml) embedded in the assembly resources or in the code, using strings.
                                The old GetSchema method was replaced by the ExtendModelInterfaces(ModelInterfaceExtenders extenders) method in the ModuleBase and Controller classes.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Application"> <Element Name="Views"> <Element Name="ListView"> <Element Name="Variants" > <Attribute Name="Current" /> <Element Name="Variant" > <Attribute Name="ID" /> <Attribute Name="Caption" /> <Attribute Name="ViewID" /> </Element> </Element> </Element> </Element> </Element>
                                [C#]
                                public sealed class ViewVariantsModule : Module { public override Schema GetSchema() { return new Schema(new DictionaryXmlReader().ReadFromResource(GetType().Assembly, "Schema.xml")); } }
                                [VB.NET]
                                Public NotInheritable Class ViewVariantsModule Inherits Module Public Overrides Function GetSchema() As Schema Return New Schema(New DictionaryXmlReader().ReadFromResource(Me.GetType().Assembly, "Schema.xml")) End Function End Class

                                NOW:

                                [C#]
                                public interface IModelViewVariants : IModelNode { IModelVariants Variants { get; set; } } public interface IModelVariants : IModelNode, IModelList<IModelVariant> { IModelVariant Current { get; set; } } public interface IModelVariant : IModelNode { string Id { get; set; } string ViewID { get; set; } string Caption { get; set; } } public sealed class ViewVariantsModule : Module { public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders) { base.ExtendModelInterfaces(extenders); extenders.Add<IModelView, IModelViewVariants>(); } }
                                [VB.NET]
                                Public Interface IModelViewVariants Inherits IModelNode Property Variants() As IModelVariants End Interface Public Interface IModelVariants Inherits IModelNode, IModelList(Of IModelVariant) Property Current() As IModelVariant End Interface public Interface IModelVariant Inherits IModelNode Property Id() As String Property ViewID() As String Property Caption() As String End Interface Public NotInheritable Class ViewVariantsModule Inherits Module Public Overrides Sub ExtendModelInterfaces(ByVal extenders As ModelInterfaceExtenders) MyBase.ExtendModelInterfaces(extenders) extenders.Add(Of IModelView, IModelViewVariants)() End Sub End Class

                                Take special note, that if you extend an existing model interface, then you should either:
                                a) Create a new interface supporting the base IModelNode interface. In this case the explicit registration is necessary:

                                [C#]
                                [ModelPersistentName("DWWebClient")] public interface IModelNavigationItemEx : IModelNode { IModelDWWebClients DWWebClients { get; } } public interface IModelDWWebClients : IModelNode, IModelList<IModelDWWebClient> { ... } public interface IModelDWWebClient : IModelNode { string Categories { get; set; } } public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders) { extenders.Add<IModelNavigationItem, IModelNavigationItemEx>(); } [Test] public void Extention1() { IModelNavigationItem modelNode = (IModelNavigationItem)ApplicationCreator.CreateNode(null, null, typeof(IModelNavigationItem)); Assert.IsNotNull(modelNode); Assert.IsTrue(modelNode is IModelNavigationItemEx); }
                                [VB.NET]
                                <ModelPersistentName("DWWebClient")> _ Public Interface IModelNavigationItemEx Inherits IModelNode ReadOnly Property DWWebClients() As IModelDWWebClients End Interface Public Interface IModelDWWebClients Inherits IModelNode, IModelList(Of IModelDWWebClient) End Interface Public Interface IModelDWWebClient Inherits IModelNode Property Categories() As String End Interface Public Overrides Sub ExtendModelInterfaces(ByVal extenders As ModelInterfaceExtenders) extenders.Add(Of IModelNavigationItem, IModelNavigationItemEx)() End Sub <Test> _ public Sub Extention1() Dim modelNode As IModelNavigationItem = CType(ApplicationCreator.CreateNode(Nothing, Nothing, GetType(IModelNavigationItem)), IModelNavigationItem) Assert.IsNotNull(modelNode) Assert.IsTrue(TypeOf modelNode Is IModelNavigationItemEx) End Sub

                                b) Create a new interface supporting the existing interface. In this case the explicit registration is NOT necessary:

                                [C#]
                                [ModelPersistentName("DWWebClient")] public interface IModelDWWebClient : IModelNavigationItem { string Categories { get; set; } } [Test] public void Extention1() { IModelNavigationItems modelNode = (IModelNavigationItems)ApplicationCreator.CreateNode(null, null, typeof(IModelNavigationItems)); IModelDWWebClient item = modelNode.AddNode<IModelDWWebClient>("myCustom"); item.Categories = "xxx"; Assert.AreEqual("xxx", ((IModelDWWebClient)modelNode["myCustom"]).Categories); }
                                [VB.NET]
                                <ModelPersistentName("DWWebClient")> _ Public Interface IModelDWWebClient Inherits IModelNavigationItem Property Categories() As String End Interface <Test> _ Public Sub Extention1() Dim modelNode As IModelNavigationItems = CType(ApplicationCreator.CreateNode(Nothing, Nothing, GetType(IModelNavigationItems)), IModelNavigationItems) Dim item As IModelDWWebClient = modelNode.AddNode(Of IModelDWWebClient)("myCustom") item.Categories = "xxx" Assert.AreEqual("xxx", (CType(modelNode("myCustom"), IModelDWWebClient)).Categories) End Sub

                                =========================================
                                2. Declaring a key attribute for an element.
                                Now, you should mark the corresponding model interface with the DevExpress.ExpressApp.Model.KeyPropertyAttribute.
                                Previously, the KeyAttribute could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant" KeyAttribute="ID" />

                                NOW:

                                [C#]
                                [KeyProperty("Id")] public interface IModelEditorStateRule : IEditorStateRule { string Id { get; set; } }
                                [VB.NET]
                                <KeyProperty("Id")> _ Public Interface IModelEditorStateRule Inherits IEditorStateRule Property Id() As String End Interface

                                Take special note that you should not use the 'ID' property at all (all characters are in upper case). It is not recognized as a key property and is not initialized by the 'Add(string id)' and similar methods.
                                Instead, declare the 'Id' property (the last character is in lower case). This property will always be the key even if the KeyPropertyAttribute doesn't point to it.
                                However, it's recommended that you use the KeyPropertyAttribute to explicitly specify a key attribute.
                                Also, take special note that you should not specify the word "Application" as an Id for any element in the application model.
                                =========================================
                                3. Declaring a list of child elements for a parent element.
                                Now you should define an interface supporting the generic IModelList interface and add a child list property into the interface, corresponding to the parent element.
                                Before the Multiple attribute can be set to True in the child element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variants"> <Element Name="Variant" Multiple="True" ... /> </Element>

                                NOW:

                                [C#]
                                public interface IModelViewVariants : IModelNode { IModelVariants Variants { get; set; } } public interface IModelVariants : IModelNode, IModelList<IModelVariant> { ... } public interface IModelVariant : IModelNode { ... }
                                [VB.NET]
                                Public Interface IModelViewVariants Inherits IModelNode Property Variants() As IModelVariants End Interface Public Interface IModelVariants Inherits IModelNode, IModelList(Of IModelVariant) ... End Interface Public Interface IModelVariant Inherits IModelNode ... End Interface

                                Take special note that such list properties must only have a getter. The setter is not allowed. Consider the following pattern:

                                [C#]
                                public interface IModelXXX : IModelList<IModelZZZ> { ... } public interface IModelYYY { IModelXXX XXX { get; } //It's all right. IModelXXX XXX { get; set } //It's incorrect because the property has setter. }
                                [VB.NET]
                                Public Interface IModelXXX Inherits IModelList(Of IModelZZZ) ... End Interface Public Interface IModelYYY ReadOnly Property XXX() As IModelXXX 'It's all right. Property XXX() As IModelXXX 'It's incorrect because the property has setter. End Interface

                                Also, take special note that in VB.NET, when accessing a child element of the IModelList property via indexer, you may receive the "Default property access is ambiguous between the inherited interface members" compilation error. In this case, you should check the following help topic in MSDN: http://msdn.microsoft.com/en-us/library/dw17e1fw.aspx
                                =========================================
                                4. Declaring a localizable attribute for an element.
                                Now you should mark the required interface property with the System.ComponentModel.LocalizableAttribute.,
                                Previously, the IsLocalized attribute could be set to True in the attribute definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant"> <Attribute Name="Caption" IsLocalized="True" />

                                NOW:

                                [C#]
                                public interface IModelVariant : IModelNode { [Localizable(true)] string Caption { get; set; } }
                                [VB.NET]
                                Public Interface IModelVariant Inherits IModelNode <Localizable(True)> _ Property Caption() As String End Interface

                                =========================================
                                5. Specifying an image for an element.
                                Now you should mark the corresponding application model interface with the DevExpress.Persistent.Base.ImageNameAttribtute.
                                Previously, the ImageName attribute could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant" ImageName="ModelEditor_ListView"/>

                                NOW:

                                [C#]
                                [ImageName("ModelEditor_ListView")] public interface IModelVariant : IModelNode { ... }
                                [VB.NET]
                                <ImageName("ModelEditor_ListView")> Public Interface IModelVariant Inherits IModelNode ... End Interface

                                =========================================
                                6. Specifying a display name for an element.
                                Now, you should mark the corresponding model interface with the DevExpress.ExpressApp.Model.DisplayAttribute.
                                Previously, the DisplayAttribute could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant" DisplayAttribute="Caption" .../>

                                NOW:

                                [C#]
                                [DisplayProperty("Caption")] public interface IModelVariant : IModelNode { ... }
                                [VB.NET]
                                Public Interface IModelVariant Inherits IModelNode ... End Interface

                                =========================================
                                7. Specifying a required attribute for an element.
                                Now you should mark the corresponding model interface with the DevExpress.ExpressApp.Model.RequiredAttribute.
                                Previously, the Required could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant" > <Attribute Name="ViewID" Required="True" />

                                NOW:

                                [C#]
                                public interface IModelVariant : IModelNode { [Required()] string ViewID { get; set; } }
                                [VB.NET]
                                Public Interface IModelVariant Inherits IModelNode <Required()> _ Property ViewID() As String End Interface

                                =========================================
                                8. Specifying an order of an element.
                                Now you should not do anything special for that. The Index attribute is available for all the model elements since it's derived from the IModelNode interface.
                                Previously, the Index could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variant" > <Attribute Name="Index" IsNewNode="True"/>

                                Take special note that the Index attribute is now also used instead of the old VisibleIndex property (for example, in the ColumnInfo element).
                                =========================================
                                9. Declaring a simple reference to another element.
                                Now you should mark the required interface property with the DevExpress.Persistent.Base.DataSourcePropertyAttribute.
                                Take special note that you can also filter the data source with the help of the DevExpress.Persistent.Base.DataSourceCriteriaAttribute.
                                Previously, the RefNodeName attribute could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Attribute Name=""TypeInfo"" Required=""True"" RefNodeName=""/Application/BOModel/Class""/> <Element Name="Validation"> <Element Name="Contexts"> <Attribute Name="DefaultSavingValidationContext"/>


                                NOW:

                                [C#]
                                [DataSourceProperty("Application.BOModel")] IModelClass ModelClass { get; set; }
                                [VB.NET]
                                <DataSourceProperty("Application.BOModel")> _ Property ModelClass() As IModelClass

                                Take special note that you can use the "this" keyword to specify that a value should be selected from the current node (this node should implement the IModelList<XXX> interface - this is a basic requirement for data sources for application model elements)
                                PREVIOUSLY:

                                [XML]
                                <Element Name="Validation"> <Element Name="Contexts"> <Attribute Name="DefaultSavingValidationContext"/>

                                NOW:

                                [C#]
                                public interface IModelValidationContexts_Ext : IModelValidationContexts { [DataSourceProperty("this")] IModelValidationContext DefaultSavingValidationContext { get; set; } }
                                [VB.NET]
                                Public Interface IModelValidationContexts_Ext Inherits IModelValidationContexts <DataSourceProperty("this")> _ Property DefaultSavingValidationContext() As IModelValidationContext End Interface

                                =========================================
                                10. Declaring a complex reference to another element.
                                Complex references,
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.ListViewEditorTypeRefProvider}
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.ViewIdRefNodeProvider}ClassName=@ClassName;ViewType=DetailView"
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.RefNodePropertyProvider}ClassName=..\..\@ClassName"
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.PropertyEditorRefNodeProvider}PropertyType=@Type"
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.ListViewEditorTypeRefProvider}"
                                - "{DevExpress.ExpressApp.Core.DictionaryHelpers.ChildrenRefNodeProvider}"

                                that were set via the AttributeRefNodeProvider descendants are not supported in the new application model.
                                Now you can use the DC technology and the DevExpress.ExpressApp.DC.DomainLogicAttribute it provides to assign the default logic to an element.
                                The DataSourceProperty and DataSourceCriteria attributes described in the 9th point can be used as well.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Variants" IsNewNode="True" ImageName="ModelEditor_Views"> <Attribute Name="Current" RefNodeName="{DevExpress.ExpressApp.Core.DictionaryHelpers.ChildrenRefNodeProvider}" IsNewNode="True"/> <Element Name="Variant" KeyAttribute="ID" DisplayAttribute="Caption" Multiple="True" IsNewNode="True" ImageName="ModelEditor_DetailView"> <Attribute Name="ID" Required="True" IsNewNode="True"/> <Attribute Name="Caption" IsLocalized="True" IsNewNode="True"/> <Attribute Name="ViewID" Required="True" RefNodeName="{DevExpress.ExpressApp.Core.DictionaryHelpers.ViewIdRefNodeProvider}ClassName=..\..\@ClassName;ViewType=DetailView; IncludeBaseClasses=True" IsNewNode="True"/> <Attribute Name="Index" IsNewNode="True"/> </Element> </Element> ... <Attribute Name="ViewID" Required="True" RefNodeName="{DevExpress.ExpressApp.Core.DictionaryHelpers.ViewIdRefNodeProvider}ClassName=@Name;ViewType=ListView" IsNewNode="True"/>

                                NOW:

                                [C#]
                                public interface IModelVariant : IModelNode { string Id { get; set; } [Browsable(false)] CalculatedModelNodeList<IModelView> Views { get; } [Required()] [DataSourceProperty("Views")] [ModelPersistentName("ViewID")] [Category("Appearance")] IModelView View { get; set; } [Localizable(true)] string Caption { get; set; } } [DomainLogic(typeof(IModelVariant))] public static class ModelVariantLogic { public static CalculatedModelNodeList<IModelView> Get_Views(IModelVariant modelVariant) { CalculatedModelNodeList<IModelView> views = new CalculatedModelNodeList<IModelView>(); if(modelVariant.Parent == null) { return views; } IModelView parentView = modelVariant.Parent.Parent as IModelView; if(parentView == null || parentView.ModelClass == null) { return views; } Type parentViewType = parentView.GetType(); foreach(IModelView modelView in modelVariant.Application.Views) { if(modelView.ModelClass != null && modelView.ModelClass.Name == parentView.ModelClass.Name) { if(modelView.GetType() == parentViewType) views.Add(modelView); } } return views; } } ... [DataSourceCriteria("ModelClass Is Not Null And ModelClass.Name = '@This.Name'")] IModelListView DefaultListView { get; set; }
                                [VB.NET]
                                Public Interface IModelVariant Inherits IModelNode Property Id() As String <Browsable(False)> _ ReadOnly Property Views() As CalculatedModelNodeList(Of IModelView) <Required(), DataSourceProperty("Views"), ModelPersistentName("ViewID")> _ Property View() As IModelView <Localizable(True)> _ Property Caption() As String End Interface <DomainLogic(GetType(IModelVariant))> _ Public NotInheritable Class ModelVariantLogic Private Sub New() End Sub Public Shared Function Get_Views(ByVal modelVariant As IModelVariant) As CalculatedModelNodeList(Of IModelView) Dim views As New CalculatedModelNodeList(Of IModelView)() If modelVariant.Parent Is Nothing Then Return views End If Dim parentView As IModelView = TryCast(modelVariant.Parent.Parent, IModelView) If parentView Is Nothing OrElse parentView.ModelClass Is Nothing Then Return views End If Dim parentViewType As Type = CType(parentView, Object).GetType() For Each modelView As IModelView In modelVariant.Application.Views If modelView.ModelClass IsNot Nothing AndAlso modelView.ModelClass.Name = parentView.ModelClass.Name Then If CType(modelView, Object).GetType() Is parentViewType Then views.Add(modelView) End If End If Next modelView Return views End Function End Class ... <DataSourceCriteria("ModelClass Is Not Null And ModelClass.Name = '@This.Name'")> _ Property DefaultListView() As IModelListView

                                Take special note of the use of the CalculatedModelNodeList<IModelXXX> class.
                                It's used when you need to provide a custom list of model elements (supporting the IModelNode interface).
                                It's very similar to Scenario 4 of filtering lookups described here.
                                =========================================
                                11. Declaring a choice for a drop down list for an attribute.
                                Now you should define an enumeration property, containing possible choices, in your model interface.
                                Previously, the Choice attribute could be set in the element definition with the list of choice values separated by commas.
                                Take special note that the AllowCustom attribute is not supported anymore.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="NavigationItems" > <Attribute Name=""DefaultChildItemsDisplayStyle"" Choice=""List,LargeIcons""/> <Attribute Name=""Color"" Required=""True"" Choice=""{System.Drawing.KnownColor}"" AllowCustom=""True""/>

                                NOW:

                                [C#]
                                public interface IModelNavigationItems : IModelNode { ItemsDisplayStyle DefaultChildItemsDisplayStyle { get; set; } } public interface IModelConditionalFormattingTarget : IModelNode { Color Color { get; set; } }
                                [VB.NET]
                                Public Interface IModelNavigationItems Inherits IModelNode Property DefaultChildItemsDisplayStyle() As ItemsDisplayStyle End Interface Public Interface IModelConditionalFormattingTarget Inherits IModelNode Property Color() As Color End Interface

                                =========================================
                                12. Obtaining data from standard elements.
                                Now you should use strongly-typed approach and access data via interfaces suggesting by the Visual Studio IntelliSense.
                                Previously, you had to deal either with strings and API provided by the Dictionary and DictionaryNode classes or with node wrappers emulating a strongly-typed approach.
                                The latter classes are now deprecated, and should not be used anymore. Take special note that usually the XAF entities that have access to the application model have the Model property.

                                PREVIOUSLY:

                                [C#]
                                public PropertyEditor(Type objectType, DictionaryNode info) { ... } ... public StaticTextDetailItem(DictionaryNode info, Type objectType) { ... } ... public GridListEditor(DictionaryNode info) { ... } ... string propertyEditorType = ((DetailViewItem)item).Info.GetAttribute("PropertyEditorType").Value; ... View.Info.SetAttribute("EditorTypeName", "DevExpress.ExpressApp.Win.Editors.GridListEditor"); ... DictionaryNode viewsNode = Application.Model.RootNode.FindChildNode("Views"); ... DictionaryNode viewNode = viewsNode.FindChildNode(BaseViewInfoNodeWrapper.IdAttribute, viewId); ... new ApplicationNodeWrapper(Application.Model.RootNode).Views.FindViewById(detailViewId) ... DictionaryNode classInfoNode = Application.FindClassInfo(Type); ... columnInfo.Node.RemoveAttribute(ColumnInfoNodeWrapper.SortOrderAttribute); ... string propertyType = columnInfo.Node.GetAttributeValue("PropertyType") ... DictionaryNode filtersInfo = View.Info.FindChildNode("Filters"); ... bool showAutoFilterRow = ((ListView)View).Model.ShowAutoFilterRow; ... ChoiceActionItem item = ... item.Info.SetAttribute("ImageName", "Attention"); ... foreach(ClassInfoNodeWrapper classInfo in appModel.BOModel.Classes) { foreach(PropertyInfoNodeWrapper propertyInfo in classInfo.Properties) { string itemType = propertyInfo.IsCollection ? propertyInfo.CollectionElementType : propertyInfo.Type; } } ... ColumnInfoNodeWrapper sortByColumn = null; if(typeof(ITimeLimited).IsAssignableFrom(listViewInfo.BusinessObjectType)) { sortByColumn = listViewInfo.Columns.FindColumnInfo("FixTo"); } ... foreach(DetailViewItemInfoNodeWrapper itemInfo in detailViewInfo.Editors.Items) { if(toDelete.Contains(itemInfo.View)) { itemInfo.View = null; } } ...
                                [VB.NET]
                                Inherits PropertyEditor Public Sub New(ByVal objectType As Type, ByVal info As DictionaryNode) ... End Sub ... Inherits StaticTextDetailItem Public Sub New(ByVal info as DictionaryNode, ByVal objectType As Type) ... End Sub ... Inherits GridListEditor Public Sub New(ByVal info as DictionaryNode) ... End Sub ... Dim propertyEditorType As String = (CType(item, DetailViewItem)).Info.GetAttribute("PropertyEditorType").Value ... View.Info.SetAttribute("EditorTypeName", "DevExpress.ExpressApp.Win.Editors.GridListEditor") ... Dim viewsNode As DictionaryNode = Application.Model.RootNode.FindChildNode("Views") ... Dim viewNode As DictionaryNode = viewsNode.FindChildNode(BaseViewInfoNodeWrapper.IdAttribute, viewId) ... CType(New ApplicationNodeWrapper(Application.Model.RootNode), ApplicationNodeWrapper).Views.FindViewById(detailViewId) DictionaryNode classInfoNode = Application.FindClassInfo(Type) ... columnInfo.Node.RemoveAttribute(ColumnInfoNodeWrapper.SortOrderAttribute) ... Dim propertyType As String = columnInfo.Node.GetAttributeValue("PropertyType") DictionaryNode filtersInfo = View.Info.FindChildNode("Filters") ... Dim showAutoFilterRow As Boolean = (CType(View, ListView)).Model.ShowAutoFilterRow ... Dim item As ChoiceActionItem = Nothing item.Info.SetAttribute("ImageName", "Attention") ... For Each classInfo As ClassInfoNodeWrapper In appModel.BOModel.Classes For Each propertyInfo As PropertyInfoNodeWrapper In classInfo.Properties Dim itemType As String = If(propertyInfo.IsCollection, propertyInfo.CollectionElementType, propertyInfo.Type) Next propertyInfo Next classInfo ... Dim sortByColumn As ColumnInfoNodeWrapper = Nothing If GetType(ITimeLimited).IsAssignableFrom(listViewInfo.BusinessObjectType) Then sortByColumn = listViewInfo.Columns.FindColumnInfo("FixTo") End If ... For Each itemInfo As DetailViewItemInfoNodeWrapper In detailViewInfo.Editors.Items If toDelete.Contains(itemInfo.View) Then itemInfo.View = Nothing End If Next itemInfo ...

                                NOW:

                                [C#]
                                public PropertyEditor(Type objectType, IModelMemberViewItem info) { ... } ... public StaticTextDetailItem(IModelStaticText model, Type objectType) { ... } ... public GridListEditor(IModelListView model) { ... } ... PropertyEditor editor = (PropertyEditor)View.FindItem("Amount"); string propertyEditorType= editor.GetType().FullName; ... View.Model.EditorType = typeof(DevExpress.ExpressApp.Win.Editors.GridListEditor); ... IModelView modelView = Application.Model.Views[viewId]; ... Application.Model.Views[detailViewId] ... IModelClass modelClass = Application.ModelApplication.BOModel[type.FullName]; ... columnInfo.SortOrder = DevExpress.Data.ColumnSortOrder.None; ... string propertyType = columnInfo.ModelMember.Type.FullName; ... IModelListViewFilters modelListViewFilters = (View.Model as IModelListViewFilter).Filters; ... bool showAutoFilterRow = (IModelListViewShowAutoFilterRow)((ListView)View).Model).ShowAutoFilterRow; ... ChoiceActionItem item = ... ((IModelChoiceActionItem)item.Model).ImageName = "Attention"; ... foreach(IModelClass classInfo in appModel.BOModel) { foreach(IModelMember propertyInfo in classInfo.OwnMembers) { string itemType = propertyInfo.MemberInfo.IsList ? propertyInfo.MemberInfo.ListElementType.FullName : propertyInfo.Type.FullName; } } ... IModelColumn sortByColumn = null; if(typeof(ITimeLimited).IsAssignableFrom(listViewInfo.ModelClass.TypeInfo.Type)) { sortByColumn = listViewInfo.Columns["FixTo"]; } ... foreach(IModelDetailViewItem itemInfo in detailViewInfo.Items) { IModelMemberViewItem memberItemInfo = itemInfo as IModelMemberViewItem; if(memberItemInfo != null && toDelete.Contains(memberItemInfo.View)) { memberItemInfo.View = null; } } ...
                                [VB.NET]
                                Inherits PropertyEditor Public Sub New(ByVal objectType As Type, ByVal info As IModelMemberViewItem) ... End Sub ... Inherits StaticTextDetailItem Public Sub New(ByVal info as IModelStaticText, ByVal objectType As Type) ... End Sub ... Inherits GridListEditor Public Sub New(ByVal model As IModelListView) ... End Sub ... Dim editor As PropertyEditor = CType(View.FindItem("Amount"), PropertyEditor) Dim propertyEditorType As String= editor.GetType().FullName ... View.Model.EditorType = GetType(DevExpress.ExpressApp.Win.Editors.GridListEditor) ... Dim modelView As IModelView = Application.Model.Views(viewId) ... Application.Model.Views(detailViewId) IModelClass modelClass = Application.ModelApplication.BOModel(type.FullName) ... columnInfo.SortOrder = DevExpress.Data.ColumnSortOrder.None ... Dim propertyType As String = columnInfo.ModelMember.Type.FullName ... Dim modelListViewFilters As IModelListViewFilters = (TryCast(View.Model, IModelListViewFilter)).Filters ... Dim showAutoFilterRow As Boolean = CType((CType(View, ListView)).Model, IModelListViewShowAutoFilterRow)).ShowAutoFilterRow ... Dim item As ChoiceActionItem = ... CType(item.Model, IModelChoiceActionItem).ImageName = "Attention" ... For Each classInfo As IModelClass In appModel.BOModel For Each propertyInfo As IModelMember In classInfo.OwnMembers Dim itemType As String = If(propertyInfo.MemberInfo.IsList, propertyInfo.MemberInfo.ListElementType.FullName, propertyInfo.Type.FullName) Next propertyInfo Next classInfo ... Dim sortByColumn As IModelColumn = Nothing If GetType(ITimeLimited).IsAssignableFrom(listViewInfo.ModelClass.TypeInfo.Type) Then sortByColumn = listViewInfo.Columns("FixTo") End If ... For Each itemInfo As IModelDetailViewItem In detailViewInfo.Items Dim memberItemInfo As IModelMemberViewItem = TryCast(itemInfo, IModelMemberViewItem) If memberItemInfo IsNot Nothing AndAlso toDelete.Contains(memberItemInfo.View) Then memberItemInfo.View = Nothing End If Next itemInfo ...

                                =========================================
                                13. Obtaining data from custom (extended) elements.
                                Now you should find the extended element and then cast it to the extended model interface and then access its properties.
                                Previously, you could use the GetAttributeXXXValue methods and pass the name of the extension property as a parameter.

                                PREVIOUSLY:

                                [C#]
                                DictionaryNode viewNode = viewsNode.FindChildNode(BaseViewInfoNodeWrapper.IdAttribute, viewId); string myCustomFilter = viewNode.GetAttributeValue("MyCustomFilter");
                                [VB.NET]
                                Dim viewNode As DictionaryNode = viewsNode.FindChildNode(BaseViewInfoNodeWrapper.IdAttribute, viewId) Dim myCustomFilter As String = viewNode.GetAttributeValue("MyCustomFilter")

                                NOW:

                                [C#]
                                IModelViewMyCustomFilterExtention myModelView = (IModelViewMyCustomFilterExtention)Application.ModelApplication.Views[viewId]; string myCustomAttrValue = myModelView.MyCustomFilter;
                                [VB.NET]
                                Dim myModelView As IModelViewMyCustomFilterExtention = CType(Application.ModelApplication.Views(viewId), IModelViewMyCustomFilterExtention) Dim myCustomAttrValue As String = myModelView.MyCustomFilter

                                =========================================
                                14. Specifying a static default value when obtaining data from an element.
                                Now you should mark the required interface property with the System.ComponentModel.DefaultValueAttribute.
                                Previously, you could pass the parameter in the GetAttributeXXXValue methods.

                                PREVIOUSLY:

                                [C#]
                                bool allowValue = dictionaryNode.GetAttributeBoolValue("Allow", false);
                                [VB.NET]
                                Dim allowValue As Boolean = dictionaryNode.GetAttributeBoolValue("Allow", False)

                                NOW:

                                [C#]
                                public interface IModelMyExtention : IModelNode { [DefaultValue(false)] bool Allow { get; set; }
                                [VB.NET]
                                Public Interface IModelMyExtention Inherits IModelNode <DefaultValue(False)> _ Property Allow() As Boolean End Interface

                                =========================================
                                15. Specifying a calculated default value when obtaining data from an element.
                                Now you can use the DC technology and the DevExpress.ExpressApp.DC.DomainLogicAttribute it provides to assign the default domain logic for an element.
                                Previously, you could override the UpdateModel method of the ModuleBase and Controller classes or use the IModelCustomizer classes.

                                PREVIOUSLY:

                                [C#]
                                public override void UpdateModel(Dictionary model) { EventListViewCustomizer eventListViewCustomizer = new EventListViewCustomizer(); eventListViewCustomizer.Customize(model); } public class EventListViewCustomizer : ViewCustomizer<ListViewInfoNodeWrapper> { private String resourceClassName = ""; protected override void OnView(ListViewInfoNodeWrapper info) { info.Node.SetAttribute("ResourceClassName", resourceClassName); } public EventListViewCustomizer() { IEnumerable<ITypeInfo> resourceTypes = ReflectionHelper.FindTypeDescendants(XafTypesInfo.Instance.FindTypeInfo(typeof(IResource))); ITypeInfo firstResourceInfo = Enumerator.GetFirst<ITypeInfo>(resourceTypes); if(firstResourceInfo != null) { resourceClassName = firstResourceInfo.FullName; } } }
                                [VB.NET]
                                Public Overrides Sub UpdateModel(ByVal model As Dictionary) Dim eventListViewCustomizer As New EventListViewCustomizer() eventListViewCustomizer.Customize(model) End Sub Public Class EventListViewCustomizer Inherits ViewCustomizer(Of ListViewInfoNodeWrapper) Private resourceClassName As String = "" Protected Overrides Sub OnView(ByVal info As ListViewInfoNodeWrapper) info.Node.SetAttribute("ResourceClassName", resourceClassName) End Sub Public Sub New() Dim resourceTypes As IEnumerable(Of ITypeInfo) = ReflectionHelper.FindTypeDescendants(XafTypesInfo.Instance.FindTypeInfo(GetType(IResource))) Dim firstResourceInfo As ITypeInfo = Enumerator.GetFirst(Of ITypeInfo)(resourceTypes) If firstResourceInfo IsNot Nothing Then resourceClassName = firstResourceInfo.FullName End If End Sub End Class

                                NOW:

                                [C#]
                                public interface IModelListViewScheduler { IModelClass ResourceClass { get; set; } } [DomainLogic(typeof(IModelListViewScheduler))] public static class ResourceClassDomainLogic { public static IModelClass Get_ResourceClass(IModelListViewScheduler modelListView) { foreach(IModelClass modelClass in ((IModelListView)modelListView).Application.BOModel) { if(typeof(IResource).IsAssignableFrom(modelClass.TypeInfo.Type)) { return modelClass; } } return null; } }
                                [VB.NET]
                                Public Interface IModelListViewScheduler Property ResourceClass() As IModelClass End Interface <DomainLogic(GetType(IModelListViewScheduler))> _ Public NotInheritable Class ResourceClassDomainLogic Private Sub New() End Sub Public Shared Function Get_ResourceClass(ByVal modelListView As IModelListViewScheduler) As IModelClass For Each modelClass As IModelClass In (CType(modelListView, IModelListView)).Application.BOModel If GetType(IResource).IsAssignableFrom(modelClass.TypeInfo.Type) Then Return modelClass End If Next modelClass Return Nothing End Function End Class

                                =========================================
                                16. Specifying a calculated default value against another element.
                                Now you should also use the same approach as described above.
                                Previously, the DefaultValueExpr attribute, pointing to the AttributeValueCalculator class containing the logic, can be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name=""NavigationItems"" ImageName=""ModelEditor_Navigation_Items""> <Attribute Name=""Caption"" DefaultValueExpr=""{DevExpress.ExpressApp.Core.DictionaryHelpers.NavigationItemCaptionPropertyCalculator}""/>

                                NOW:

                                [C#]
                                [DomainLogic(typeof(IModelBaseChoiceActionItem))] public static class ModelNavigationItemDomainLogic { public static string Get_Caption(IModelBaseChoiceActionItem item) { IModelNavigationItem navigationItem = item as IModelNavigationItem; if(navigationItem != null && navigationItem.View != null) { return navigationItem.View.Caption; } return item.Id; }
                                [VB.NET]
                                <DomainLogic(GetType(IModelBaseChoiceActionItem))> _ Public NotInheritable Class ModelNavigationItemDomainLogic Private Sub New() End Sub Public Shared Function Get_Caption(ByVal item As IModelBaseChoiceActionItem) As String Dim navigationItem As IModelNavigationItem = TryCast(item, IModelNavigationItem) If navigationItem IsNot Nothing AndAlso navigationItem.View IsNot Nothing Then Return navigationItem.View.Caption End If Return item.Id End Function

                                =========================================
                                17. Specifying a calculated default value against an attribute of another element.
                                Now you can use the ModelValueCalculatorAttribute and specify its source element and attribute parameters.
                                Alternatively, you can use the DevExpress.ExpressApp.DC.DomainLogicAttribute to assign a domain logic for an element.
                                Previously, the DefaultValueExpr attribute, pointing to the required SourceNode and SourceAttribute, could be set in the element definition.

                                PREVIOUSLY:

                                [XML]
                                <Element Name="Validation"> <Element Name="Contexts"> <Attribute Name="DefaultSavingValidationContext"/> <Attribute Name="DefaultDeletingValidationContext"/> </Element> </Element> <Element Name="DetailView"> <Attribute Name="SavingValidationContext" DefaultValueExpr="SourceNode=Validation\Contexts; SourceAttribute=@DefaultSavingValidationContext"/> <Attribute Name="DeletingValidationContext" DefaultValueExpr="SourceNode=Validation\Contexts; SourceAttribute=@DefaultDeletingValidationContext"/> </Element> <Attribute Name="ListCaption" IsLocalized="True" DefaultValueExpr="SourceNode=BOModel\Class\@Name=@Name; SourceAttribute=@Caption"/> <Attribute Name="DefaultLookupEditorMode" Choice="{DevExpress.Persistent.Base.LookupEditorMode}" DefaultValueExpr="SourceNode=BOModel\Class\@Name=@BaseClassName; SourceAttribute=@DefaultLookupEditorMode"/> ... <Attribute Name="FriendlyKeyProperty" DefaultValueExpr="SourceNode=BOModel\Class\@Name=@BaseClassName; SourceAttribute=@FriendlyKeyProperty" />

                                NOW:

                                [C#]
                                public interface IModelValidationContextsExtender : IModelValidationContexts { string DefaultSavingValidationContext { get; set; } string DefaultDeletingValidationContext { get; set; } } public interface IModelDetailViewExtender : IModelNode { [ModelValueCalculator("Application.Validation.Contexts", "DefaultSavingValidationContext")] string SavingValidationContext { get; set; } [ModelValueCalculator("Application.Validation.Contexts", "DefaultDeletingValidationContext")] string DeletingValidationContext { get; set; } } public interface IModelClassExtender : IModelNode { [Localizable(true)] [ModelValueCalculator("Caption")] string ListCaption { get; set; } LookupEditorMode DefaultLookupEditorMode { get; set; } string SimpleCreationDetailViewID { get; set; } } DomainLogic(typeof(IModelClassExtender))] public static class ModelClassExtenderLogic { public static LookupEditorMode Get_LookupEditorMode(IModelClassExtender modelExtender) { IModelClass modelClass = modelExtender.Application.BOModel[((IModelMember)modelExtender).Type.BaseType.FullName]; if(modelClass != null) { return modelExtender.DefaultLookupEditorMode; } return LookupEditorMode.Auto; } } ... [ModelValueCalculator("BaseClass", "FriendlyKeyProperty")] string FriendlyKeyProperty { get; set; }
                                [VB.NET]
                                Public Interface IModelValidationContextsExtender Inherits IModelValidationContexts Property DefaultSavingValidationContext() As String Property DefaultDeletingValidationContext() As String End Interface Public Interface IModelDetailViewExtender Inherits IModelNode <ModelValueCalculator("Application.Validation.Contexts", "DefaultSavingValidationContext")> _ Property SavingValidationContext() As String <ModelValueCalculator("Application.Validation.Contexts", "DefaultDeletingValidationContext")> _ Property DeletingValidationContext() As String End Interface Public Interface IModelClassExtender Inherits IModelNode <Localizable(True), ModelValueCalculator("Caption")> _ Property ListCaption() As String Property DefaultLookupEditorMode() As LookupEditorMode Property SimpleCreationDetailViewID() As String End Interface <DomainLogic(GetType(IModelClassExtender))> _ Public NotInheritable Class ModelClassExtenderLogic Private Sub New() End Sub Public Shared Function Get_LookupEditorMode(ByVal modelExtender As IModelClassExtender) As LookupEditorMode Dim modelClass As IModelClass = modelExtender.Application.BOModel((CType(modelExtender, IModelMember)).Type.BaseType.FullName) If modelClass IsNot Nothing Then Return modelExtender.DefaultLookupEditorMode End If Return LookupEditorMode.Auto End Function End Class ... <ModelValueCalculator("BaseClass", "FriendlyKeyProperty")> _ Property FriendlyKeyProperty() As String

                                =========================================
                                18. Customizing classes and members.
                                Now, use the DC technology as shown in the 15th point.
                                Previously, the IObjectModelCustomLoader interface can be implemented.

                                PREVIOUSLY:

                                [C#]
                                public class AutoFilterRowListViewController : ViewController, IObjectModelCustomLoader, ISchemaUpdater { public AutoFilterRowListViewController() { TargetViewType = ViewType.ListView; } public void CustomizeClassNode(ITypeInfo classInfo, ClassInfoNodeWrapper classNode) { ListViewAutoFilterRowAttribute attr = classInfo.FindAttribute<ListViewAutoFilterRowAttribute>(); if(attr == null) { attr = ListViewAutoFilterRowAttribute.Default; } ClassInfoNodeWrapper nodeWrapper = new ClassInfoNodeWrapper(classNode.Node); nodeWrapper.DefaultListViewShowAutoFilterRow = attr.ShowAutoFilterRow; } public void CustomizeMemberNode(IMemberInfo memberInfo, PropertyInfoNodeWrapper memberNode) { ... } public override Schema GetSchema() { return new Schema(new DictionaryXmlReader().ReadFromString(@" <Element Name=""Application""> <Element Name=""BOModel""> <Element Name=""Class""> <Attribute Name=""" + ClassInfoNodeWrapper.DefaultListViewShowAutoFilterRowAttribute + @""" Choice=""True,False"" /> </Element> </Element> <Element Name=""Views""> <Element Name=""ListView""> <Attribute Name=""" + ListViewInfoNodeWrapper.ShowAutoFilterRowAttribute + @""" DefaultValueExpr=""SourceNode=BOModel\Class\@Name=@ClassName; SourceAttribute=@" + ClassInfoNodeWrapper.DefaultListViewShowAutoFilterRowAttribute + @""" Choice=""True,False"" /> </Element> </Element> </Element>")); } }
                                [VB.NET]
                                Public Class AutoFilterRowListViewController Inherits ViewController Implements IObjectModelCustomLoader, ISchemaUpdater Public Sub New() TargetViewType = ViewType.ListView End Sub Public Sub CustomizeClassNode(ByVal classInfo As ITypeInfo, ByVal classNode As ClassInfoNodeWrapper) Dim attr As ListViewAutoFilterRowAttribute = classInfo.FindAttribute(Of ListViewAutoFilterRowAttribute)() If attr Is Nothing Then attr = ListViewAutoFilterRowAttribute.Default End If Dim nodeWrapper As New ClassInfoNodeWrapper(classNode.Node) nodeWrapper.DefaultListViewShowAutoFilterRow = attr.ShowAutoFilterRow End Sub Public Sub CustomizeMemberNode(ByVal memberInfo As IMemberInfo, ByVal memberNode As PropertyInfoNodeWrapper) ... End Sub Public Overrides Function GetSchema() As Schema Return New Schema(New DictionaryXmlReader().ReadFromString("<Element Name=""Application""> " & ControlChars.CrLf & " <Element Name=""BOModel""> " & ControlChars.CrLf & " <Element Name=""Class""> " & ControlChars.CrLf & " <Attribute Name=""" & ClassInfoNodeWrapper.DefaultListViewShowAutoFilterRowAttribute & """ Choice=""True,False"" /> " & ControlChars.CrLf & " </Element> " & ControlChars.CrLf & " </Element> " & ControlChars.CrLf & " <Element Name=""Views""> " & ControlChars.CrLf & " <Element Name=""ListView""> " & ControlChars.CrLf & " <Attribute Name=""" & ListViewInfoNodeWrapper.ShowAutoFilterRowAttribute & """ " & ControlChars.CrLf & " DefaultValueExpr=""SourceNode=BOModel\Class\@Name=@ClassName; SourceAttribute=@" & ClassInfoNodeWrapper.DefaultListViewShowAutoFilterRowAttribute & """ " & ControlChars.CrLf & " Choice=""True,False"" " & ControlChars.CrLf & " /> " & ControlChars.CrLf & " </Element> " & ControlChars.CrLf & " </Element> " & ControlChars.CrLf & " </Element>")) End Function End Class

                                NOW:

                                [C#]
                                public class AutoFilterRowListViewController : ViewController, ISchemaUpdater { public AutoFilterRowListViewController() { TargetViewType = ViewType.ListView; } public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders) { base.ExtendModelInterfaces(extenders); extenders.Add<IModelClass, IModelClassShowAutoFilterRow>(); extenders.Add<IModelListView, IModelListViewShowAutoFilterRow>(); } } public interface IModelListViewShowAutoFilterRow { bool ShowAutoFilterRow { get; set; } } public interface IModelClassShowAutoFilterRow { bool DefaultListViewShowAutoFilterRow { get; set; } } [DomainLogic(typeof(IModelListViewShowAutoFilterRow))] public static class ShowAutoFilterRowDomainLogic { public static bool Get_ShowAutoFilterRow(IModelListViewShowAutoFilterRow modelListView) { if(((IModelListView)modelListView).ModelClass != null) { return ((IModelClassShowAutoFilterRow)((IModelListView)modelListView).ModelClass).DefaultListViewShowAutoFilterRow; } return false; } } [DomainLogic(typeof(IModelClassShowAutoFilterRow))] public static class ModelClassShowAutoFilterRowDomainLogic { public static bool Get_DefaultListViewShowAutoFilterRow(IModelClass modelClass) { ListViewAutoFilterRowAttribute attr = modelClass.TypeInfo.FindAttribute<ListViewAutoFilterRowAttribute>(); if(attr == null) { attr = ListViewAutoFilterRowAttribute.Default; } return attr.ShowAutoFilterRow; } }
                                [VB.NET]
                                Public Class AutoFilterRowListViewController Inherits ViewController Implements ISchemaUpdater Public Sub New() TargetViewType = ViewType.ListView End Sub public Overrides Sub ExtendModelInterfaces(ByVal extenders As ModelInterfaceExtenders) MyBase.ExtendModelInterfaces(extenders) extenders.Add(Of IModelClass, IModelClassShowAutoFilterRow)() extenders.Add(Of IModelListView, IModelListViewShowAutoFilterRow)() End Sub End Class Public Interface IModelListViewShowAutoFilterRow Property ShowAutoFilterRow() As Boolean End Interface Public Interface IModelClassShowAutoFilterRow Property DefaultListViewShowAutoFilterRow() As Boolean End Interface <DomainLogic(GetType(IModelListViewShowAutoFilterRow))> _ Public NotInheritable Class ShowAutoFilterRowDomainLogic Private Sub New() End Sub Public Shared Function Get_ShowAutoFilterRow(ByVal modelListView As IModelListViewShowAutoFilterRow) As Boolean If (CType(modelListView, IModelListView)).ModelClass IsNot Nothing Then Return (CType((CType(modelListView, IModelListView)).ModelClass, IModelClassShowAutoFilterRow)).DefaultListViewShowAutoFilterRow End If Return False End Function End Class <DomainLogic(GetType(IModelClassShowAutoFilterRow))> _ Public NotInheritable Class ModelClassShowAutoFilterRowDomainLogic Private Sub New() End Sub Public Shared Function Get_DefaultListViewShowAutoFilterRow(ByVal modelClass As IModelClass) As Boolean Dim attr As ListViewAutoFilterRowAttribute = modelClass.TypeInfo.FindAttribute(Of ListViewAutoFilterRowAttribute)() If attr Is Nothing Then attr = ListViewAutoFilterRowAttribute.Default End If Return attr.ShowAutoFilterRow End Function End Class

                                =========================================
                                19. Initializing elements during the application model generation.
                                Now you should implement a generator class implementing the ModelNodesGeneratorBase abstract class.
                                Previously, the UpdateModel(Dictionary) method of the ModuleBase or Controller classes could be used.

                                PREVIOUSLY:

                                [C#]
                                public class ConditionalEditorStateNodeWrapper : NodeWrapper { public ConditionalEditorStateNodeWrapper(DictionaryNode conditionalEditorStateNode) : base(conditionalEditorStateNode) { } public EditorStateRuleNodeWrapper AddRule() { return new EditorStateRuleNodeWrapper(Node.GetChildNode(RulesNodeName).AddChildNode(EditorStateRuleNodeWrapper.NodeName)); } public EditorStateRuleNodeWrapper AddRule(string id, ITypeInfo typeInfo, string properties, EditorState editorState, string criteria, MethodInfo methodInfo, ViewType viewType, string description) { return new EditorStateRuleNodeWrapper(Node.GetChildNode(RulesNodeName).AddChildNode(EditorStateRuleNodeWrapper.NodeName), id, typeInfo, properties, editorState, criteria, methodInfo, viewType, description); } public List<EditorStateRuleNodeWrapper> Rules { get { List<EditorStateRuleNodeWrapper> rules = new List<EditorStateRuleNodeWrapper>(); DictionaryNode rulesNode = Node.FindChildNode(RulesNodeName); if (rulesNode != null) foreach (DictionaryNode node in rulesNode.ChildNodes.GetOrderedByIndex()) if (node.Name == EditorStateRuleNodeWrapper.NodeName) { EditorStateRuleNodeWrapper wrapper = new EditorStateRuleNodeWrapper(); wrapper.Node = node; rules.Add(wrapper); } return rules; } } }
                                [VB.NET]
                                Public Class ConditionalEditorStateNodeWrapper Inherits NodeWrapper Public Sub New(ByVal conditionalEditorStateNode As DictionaryNode) MyBase.New(conditionalEditorStateNode) End Sub Public Function AddRule() As EditorStateRuleNodeWrapper Return New EditorStateRuleNodeWrapper(Node.GetChildNode(RulesNodeName).AddChildNode(EditorStateRuleNodeWrapper.NodeName)) End Function Public Function AddRule(ByVal id As String, ByVal typeInfo As ITypeInfo, ByVal properties As String, ByVal editorState As EditorState, ByVal criteria As String, ByVal methodInfo As MethodInfo, ByVal viewType As ViewType, ByVal description As String) As EditorStateRuleNodeWrapper Return New EditorStateRuleNodeWrapper(Node.GetChildNode(RulesNodeName).AddChildNode(EditorStateRuleNodeWrapper.NodeName), id, typeInfo, properties, editorState, criteria, methodInfo, viewType, description) End Function Public ReadOnly Property Rules() As List(Of EditorStateRuleNodeWrapper) Get Dim rules_Renamed As New List(Of EditorStateRuleNodeWrapper)() Dim rulesNode As DictionaryNode = Node.FindChildNode(RulesNodeName) If rulesNode IsNot Nothing Then For Each node As DictionaryNode In rulesNode.ChildNodes.GetOrderedByIndex() If node.Name = EditorStateRuleNodeWrapper.NodeName Then Dim wrapper As New EditorStateRuleNodeWrapper() wrapper.Node = node rules_Renamed.Add(wrapper) End If Next node End If Return rules_Renamed End Get End Property End Class

                                NOW:

                                [C#]
                                [ModelNodesGenerator(typeof(ConditionalEditorStateNodesGenerator))] public interface IModelRules : IModelNode, IModelList<IModelEditorStateRule> { ... } public class ConditionalEditorStateNodesGenerator : ModelNodesGeneratorBase { private void AddRules(ModelNode node, IEnumerable<EditorStateRuleAttribute> attributes, IModelClass modelClass) { AddRules(node, attributes, modelClass, string.Empty); } private void AddRules(ModelNode node, IEnumerable<EditorStateRuleAttribute> attributes, IModelClass modelClass, string methodName) { foreach (EditorStateRuleAttribute attribute in attributes) { IModelEditorStateRule rule = node.AddNode<IModelEditorStateRule>(attribute.Id); rule.Attribute = attribute; rule.ModelClass = modelClass; rule.MethodName = methodName; } } protected override void GenerateNodesCore(ModelNode node) { foreach (IModelClass modelClass in node.Application.BOModel) { AddRules(node, EditorStateRuleManager.FindAttributes(modelClass.TypeInfo), modelClass); foreach (MethodInfo methodInfo in modelClass.TypeInfo.Type.GetMethods(EditorStateRuleManager.MethodRuleBindingFlags)) AddRules(node, EditorStateRuleManager.FindAttributes(methodInfo), modelClass, methodInfo.Name); } } }
                                [VB.NET]
                                <ModelNodesGenerator(GetType(ConditionalEditorStateNodesGenerator))> _ Public Interface IModelRules Inherits IModelNode, IModelList(Of IModelEditorStateRule) ... End Interface Public Class ConditionalEditorStateNodesGenerator Inherits ModelNodesGeneratorBase Private Sub AddRules(ByVal node As ModelNode, ByVal attributes As IEnumerable(Of EditorStateRuleAttribute), ByVal modelClass As IModelClass) AddRules(node, attributes, modelClass, String.Empty) End Sub Private Sub AddRules(ByVal node As ModelNode, ByVal attributes As IEnumerable(Of EditorStateRuleAttribute), ByVal modelClass As IModelClass, ByVal methodName As String) For Each attribute As EditorStateRuleAttribute In attributes Dim rule As IModelEditorStateRule = node.AddNode(Of IModelEditorStateRule)(attribute.Id) rule.Attribute = attribute rule.ModelClass = modelClass rule.MethodName = methodName Next attribute End Sub Protected Overrides Sub GenerateNodesCore(ByVal node As ModelNode) For Each modelClass As IModelClass In node.Application.BOModel AddRules(node, EditorStateRuleManager.FindAttributes(modelClass.TypeInfo), modelClass) For Each methodInfo As MethodInfo In modelClass.TypeInfo.Type.GetMethods(EditorStateRuleManager.MethodRuleBindingFlags) AddRules(node, EditorStateRuleManager.FindAttributes(methodInfo), modelClass, methodInfo.Name) Next methodInfo Next modelClass End Sub End Class

                                =========================================
                                20. Additional updates of already created elements during the application model generation.
                                Now create a generator updater, and register it in your module by overriding the ModuleBase.AddGeneratorUpdaters method.
                                Previously, it could be done in the UpdateModel(Dictionary) method of the ModuleBase or Controller classes.

                                PREVIOUSLY:

                                [C#]
                                public class ViewVariantsModelController : Controller { public override void UpdateModel(Dictionary dictionary) { base.UpdateModel(dictionary); DictionaryNode diffsNode = new DictionaryXmlReader().ReadFromString(@" <Application> ... </Application>"); dictionary.CombineWith(new Dictionary(diffsNode, dictionary.Schema)); } }
                                [VB.NET]
                                Public Class ViewVariantsModelController Inherits Controller Public Overrides Sub UpdateModel(ByVal dictionary As Dictionary) MyBase.UpdateModel(dictionary) Dim diffsNode As DictionaryNode = New DictionaryXmlReader().ReadFromString("" & ControlChars.CrLf & "<Application>...</Application>") dictionary.CombineWith(New Dictionary(diffsNode, dictionary.Schema)) End Sub End Class

                                NOW:

                                [C#]
                                public sealed partial class MySolutionModule : ModuleBase { public Solution5Module() { InitializeComponent(); } public override void AddGeneratorUpdaters(DevExpress.ExpressApp.Model.Core.ModelNodesGeneratorUpdaters updaters) { base.AddGeneratorUpdaters(updaters); updaters.Add(new ConditionalEditorStateNodesGeneratorUpdater()); } } //See the approach suggested in the 18th point: public class ConditionalEditorStateNodesGeneratorUpdater : ModelNodesGeneratorUpdater<ConditionalEditorStateNodesGenerator> { public override void UpdateNode(ModelNode node) { ITypeInfo ti = XafTypesInfo.Instance.FindTypeInfo(typeof(FeatureCenter.Module.ConditionalEditorState.HideShowEditorsObject)); if(ti != null) { IModelEditorStateRule hideSimpleLayoutItem = node.AddNode<IModelEditorStateRule>("HideShowEditorsObject.HideSimpleLayoutItem ID"); hideSimpleLayoutItem.ModelClass = node.Application.BOModel[ti.FullName]; hideSimpleLayoutItem.Attribute = new EditorStateRuleAttribute("HideShowEditorsObject.HideSimpleLayoutItem ID", "SimpleLayoutItem", EditorState.Hidden, "HideSimpleLayoutItem = 'True'", ViewType.DetailView); IModelEditorStateRule hideSimpleLayoutGroup = node.AddNode<IModelEditorStateRule>("HideShowEditorsObject.HideSimpleLayoutGroup ID"); hideSimpleLayoutGroup.ModelClass = node.Application.BOModel[ti.FullName]; hideSimpleLayoutGroup.Attribute = new EditorStateRuleAttribute("HideShowEditorsObject.HideSimpleLayoutGroup ID", "SimpleLayoutGroup", EditorState.Hidden, "HideSimpleLayoutGroup = 'True'", ViewType.DetailView); IModelEditorStateRule hideTabPageGroup = node.AddNode<IModelEditorStateRule>("HideShowEditorsObject.HideTabPageGroup ID"); hideTabPageGroup.ModelClass = node.Application.BOModel[ti.FullName]; hideTabPageGroup.Attribute = new EditorStateRuleAttribute("HideShowEditorsObject.HideTabPageGroup ID", "TabPageGroup", EditorState.Hidden, "HideTabPageGroup = 'True'", ViewType.DetailView); } } }
                                [VB.NET]
                                Public NotInheritable Partial Class MySolutionModule Inherits ModuleBase Private Function Solution5Module() As [Public] InitializeComponent() End Function Public Overrides Sub AddGeneratorUpdaters(ByVal updaters As DevExpress.ExpressApp.Model.Core.ModelNodesGeneratorUpdaters) MyBase.AddGeneratorUpdaters(updaters) updaters.Add(New ConditionalEditorStateNodesGeneratorUpdater()) End Sub End Class 'See the approach suggested in the 18th point: Public Class ConditionalEditorStateNodesGeneratorUpdater Inherits ModelNodesGeneratorUpdater(Of ConditionalEditorStateNodesGenerator) Public Overrides Sub UpdateNode(ByVal node As ModelNode) Dim ti As ITypeInfo = XafTypesInfo.Instance.FindTypeInfo(GetType(FeatureCenter.Module.ConditionalEditorState.HideShowEditorsObject)) If ti IsNot Nothing Then Dim hideSimpleLayoutItem As IModelEditorStateRule = node.AddNode(Of IModelEditorStateRule)("HideShowEditorsObject.HideSimpleLayoutItem ID") hideSimpleLayoutItem.ModelClass = node.Application.BOModel(ti.FullName) hideSimpleLayoutItem.Attribute = New EditorStateRuleAttribute("HideShowEditorsObject.HideSimpleLayoutItem ID", "SimpleLayoutItem", EditorState.Hidden, "HideSimpleLayoutItem = 'True'", ViewType.DetailView) Dim hideSimpleLayoutGroup As IModelEditorStateRule = node.AddNode(Of IModelEditorStateRule)("HideShowEditorsObject.HideSimpleLayoutGroup ID") hideSimpleLayoutGroup.ModelClass = node.Application.BOModel(ti.FullName) hideSimpleLayoutGroup.Attribute = New EditorStateRuleAttribute("HideShowEditorsObject.HideSimpleLayoutGroup ID", "SimpleLayoutGroup", EditorState.Hidden, "HideSimpleLayoutGroup = 'True'", ViewType.DetailView) Dim hideTabPageGroup As IModelEditorStateRule = node.AddNode(Of IModelEditorStateRule)("HideShowEditorsObject.HideTabPageGroup ID") hideTabPageGroup.ModelClass = node.Application.BOModel(ti.FullName) hideTabPageGroup.Attribute = New EditorStateRuleAttribute("HideShowEditorsObject.HideTabPageGroup ID", "TabPageGroup", EditorState.Hidden, "HideTabPageGroup = 'True'", ViewType.DetailView) End If End Sub End Class

                                Take special note that to know which nodes generator updater you should inherit from, select the required application model interface in Visual Studio and then press the F12 key to see its metadata (or to invoke the Class Browser in VB.NET). There you will see the required nodes generator updater type in the ModelNodesGeneratorAttribute.
                                For example, if I want to change the IsGroupPanelVisible property value of all generated ListView elements, then I select the IModelListView in the code editor in Visual Studio and find in the interface metadata that I should inherit from the ModelListViewNodesGenerator class:

                                [C#]
                                public class MyModelListViewNodesGenerator : ModelNodesGeneratorUpdater<ModelListViewNodesGenerator> { public override void UpdateNode(ModelNode node) { IModelListView lv = (IModelListView)node; lv.IsGroupPanelVisible= false; } }
                                [VB.NET]
                                Public Class MyModelListViewNodesGenerator Inherits ModelNodesGeneratorUpdater(Of ModelListViewNodesGenerator) Public Overrides Sub UpdateNode(ByVal node As ModelNode) Dim lv As IModelListView = CType(node, IModelListView) lv.IsGroupPanelVisible= False End Sub End Class

                                =========================================
                                21. Serializing / deserializing the application model.
                                Now you should use the API provided by the ModelXmlWriter and ModelXmlReader classes.
                                Previously, the API provided by DictionaryXmlWriter and DictionaryXmlReader classes could be used.

                                PREVIOUSLY:

                                [C#]
                                string xml = new DictionaryXmlWriter(true).GetAspectXml(0, node); DictionaryNode node = new DictionaryXmlReader().ReadFromString(str);
                                [VB.NET]
                                Dim xml As String = New DictionaryXmlWriter(True).GetAspectXml(0, node) Dim node As DictionaryNode = New DictionaryXmlReader().ReadFromString(str)

                                NOW:

                                [C#]
                                string str = new ModelXmlWriter().WriteToString(View.Model, 0); new ModelXmlReader().ReadFromString(node, "", str);
                                [VB.NET]
                                Dim str As String = New ModelXmlWriter().WriteToString(View.Model, 0) CType(New ModelXmlReader(), ModelXmlReader).ReadFromString(node, "", str)

                                Here the "node" variable is an object of the IModelNode type obtained from another IModelNode object. It should correspond to the root element of the read string.
                                =========================================
                                22. Specifying visibility of properties of application model elements.
                                Now you should implement a class-calculator, supporting the DevExpress.ExpressApp.Model.IModelIsVisible interface, and provide a custom logic in its IsVisible method. After that, you can set your calculator for a specific application model property using the DevExpress.ExpressApp.Model.ModelBrowsableAttribute. It's also possible to use the System.ComponentModel.BrowsableAttribute to constantly hide properties of model elements.
                                Previously, it was possible to implement a class-calculator, descending from the AttributeVisibilityCalculator class, and provide a custom logic in its IsInvisible method. After that, you could set your calculator in the IsInvisible attribute of the element's schema (or simply set this attribute to True or False).
                                You can find examples of such calculators if you check the classes from the DevExpress.ExpressApp.Core.DictionaryHelpers namespace.

                                PREVIOUSLY:

                                [XML]
                                <Element Name=""PropertyEditor""> <Attribute IsNewNode=""True"" Name=""LinkView"" ... IsInvisible=""{DevExpress.ExpressApp.Core.DictionaryHelpers.CollectionPropertyOnly}ClassName=..\..\@ClassName"" /> </Element>

                                NOW:

                                [C#]
                                ... [Browsable(false)] IModelTemplates Templates { get; } ... [ModelBrowsable(typeof(CollectionPropertyOnlyCalculator))] IModelListView LinkView { get; set; } ... public class CollectionPropertyOnlyCalculator : IModelIsVisible { public bool IsVisible(IModelNode node, String propertyName) { IModelMember member = null; if (node is IModelMember) member = ((IModelMember)node); else if (node is IModelMemberViewItem) { member = ((IModelMemberViewItem)node).ModelMember; } if (member != null && member.MemberInfo.IsList && member.MemberInfo.ListElementType != null) { return node.Application.BOModel.GetClass(member.MemberInfo.ListElementType) != null; } return false; } }
                                [VB.NET]
                                ... <Browsable(False)> _ ReadOnly Property Templates() As IModelTemplates ... <ModelBrowsable(GetType(CollectionPropertyOnlyCalculator))> _ Property LinkView() As IModelListView ... Public Class CollectionPropertyOnlyCalculator Implements IModelIsVisible Public Function IsVisible(ByVal node As IModelNode, ByVal propertyName As String) As Boolean Dim member As IModelMember = Nothing If TypeOf node Is IModelMember Then member = (CType(node, IModelMember)) ElseIf TypeOf node Is IModelMemberViewItem Then member = (CType(node, IModelMemberViewItem)).ModelMember End If If member IsNot Nothing AndAlso member.MemberInfo.IsList AndAlso member.MemberInfo.ListElementType IsNot Nothing Then Return node.Application.BOModel.GetClass(member.MemberInfo.ListElementType) IsNot Nothing End If Return False End Function End Class

                                =========================================
                                23. Cloning elements.
                                Now you should use the CloneNodeFrom method of the ModelNode class.
                                Previously, the Clone method of the DictionaryNode class and manual initialization and adding can be used.

                                PREVIOUSLY:

                                [C#]
                                DictionaryNode viewClonedNode = viewsNode.GetChildNode("SourceView").Clone(); viewClonedNode.SetAttribute("ID", "ClonedView"); viewsNode.AddChildNode(viewClonedNode);
                                [VB.NET]
                                Dim viewClonedNode As DictionaryNode = viewsNode.GetChildNode("SourceView").Clone() viewClonedNode.SetAttribute("ID", "ClonedView") viewsNode.AddChildNode(viewClonedNode)

                                NOW:

                                [C#]
                                DevExpress.ExpressApp.Model.Core.ModelNode viewsModel = (DevExpress.ExpressApp.Model.Core.ModelNode)Application.Model.Views; IModelListView viewClonedModel = (IModelListView)viewsModel.CloneNodeFrom(viewsModel["SourceListViewId"], "ClonedListViewId");
                                [VB.NET]
                                Dim viewsModel As DevExpress.ExpressApp.Model.Core.ModelNode = CType(Application.Model.Views, DevExpress.ExpressApp.Model.Core.ModelNode) Dim viewClonedModel As IModelListView = CType(viewsModel.CloneNodeFrom(viewsModel("SourceListViewId"), "ClonedListViewId"), IModelListView)

                                =========================================
                                24. Removing elements.
                                Now it is possible to only remove child elements from the list of elements (see the 3rd point for more details). This can be done via the IModelList.Remove method.
                                Other elements can't be removed.
                                Previously, the RemoveChildNode method of the DictionaryNode class could be used.

                                PREVIOUSLY:

                                [C#]
                                viewNode.FindChildNode("Variants").RemoveChildNode(someChildViewVariantDictionaryNode);
                                [VB.NET]
                                viewNode.FindChildNode("Variants").RemoveChildNode(someChildViewVariantDictionaryNode)

                                NOW:

                                [C#]
                                ((IViewModelVariants)viewModelNode).Variants.Remove(someChildViewVariantNode);
                                [VB.NET]
                                CType(viewModelNode, IViewModelVariants).Variants.Remove(someChildViewVariantNode)

                                =========================================
                                25. Resetting elements.
                                In the simplest case now the Undo method of the ModelNode class should be used. In the complex case, the new solution now very much depends on the concrete situation in your code.
                                Before the Rollback method of the DictionaryNode class could be used.

                                PREVIOUSLY:

                                [C#]
                                DetailView.Info.Rollback();
                                [VB.NET]
                                DetailView.Info.Rollback()

                                NOW:

                                [C#]
                                ((ModelNode)(DetailView.Model)).Undo();
                                [VB.NET]
                                CType(DetailView.Model, ModelNode).Undo()

                                The ResetIsModified method of the DictionaryNode class is not supported in the new application model. If you used this method, you should change the design. The new solution now very much depends on the concrete situation in your code. Feel free to contact us in case of any difficulty.
                                =========================================
                                26. Converting application model differences and handling schema updates.
                                Instead of the ISchemaUpdater reference you should now use the IModelXmlConverter interface.
                                The IModelXmlConverter interface should be used for lightweight conversions like renaming the attribute or moving the node on another level.
                                Check out the Convert Application Model Differences help topic for more details.
                                In the forthcoming updates we will introduce events to provide complex conversions like renaming classes, etc.

                                PREVIOUSLY:

                                [C#]
                                public void ConvertDiffs(Dictionary actualModel, Dictionary diffs, Version diffsVersion) { if(diffsVersion < new Version("7.1.2.3434")) { TypedNameMap mapProperties = new TypedNameMap(); mapProperties[typeof(Organization)].Add("Property1", "FirstProperty"); mapProperties[typeof(Organization)].Add("Property2", "SecondProperty"); ModelConverterHelper.UpdateBOClassPropertyNames(diffs.RootNode, mapProperties); } }
                                [VB.NET]
                                Public Sub ConvertDiffs(ByVal actualModel As Dictionary, ByVal diffs As Dictionary, ByVal diffsVersion As Version) If diffsVersion < New Version("7.1.2.3434") Then Dim mapProperties As New TypedNameMap() mapProperties(GetType(Organization)).Add("Property1", "FirstProperty") mapProperties(GetType(Organization)).Add("Property2", "SecondProperty") ModelConverterHelper.UpdateBOClassPropertyNames(diffs.RootNode, mapProperties) End If End Sub

                                NOW:

                                [C#]
                                public void ConvertXml(ConvertXmlParameters convertXmlArgs) { if(typeof(IModelMemberViewItem).IsAssignableFrom(convertXmlArgs.NodeType)) { if (convertXmlArgs.Values.Count > 0 && !convertXmlArgs.Values.ContainsKey("Id") && convertXmlArgs.Values.ContainsKey("PropertyName")) { convertXmlArgs.Values.Add("Id", convertXmlArgs.Values["PropertyName"]); } } if(convertXmlArgs.Node is IModelClass) { if(convertXmlArgs.XmlNodeName == "Member") { IModelBOModelClassMembers members = ((IModelClass)convertXmlArgs.Node).OwnMembers; if(members == null) { members = ((IModelClass)convertXmlArgs.Node).AddNode<IModelBOModelClassMembers>("OwnMembers"); } convertXmlArgs.SubNode = members; } } if(convertXmlArgs.XmlNodeName == "NavigationItems") { if(convertXmlArgs.Values.ContainsKey("Current") && !convertXmlArgs.Values.ContainsKey("StartupNavigationItem")) { convertXmlArgs.Values.Add("StartupNavigationItem", convertXmlArgs.Values["Current"]); } } if(convertXmlArgs.XmlNodeName == "ActionRef") { convertXmlArgs.NodeType = typeof(IModelActionLink); } if(convertXmlArgs.XmlNodeName == "ColumnInfo") { convertXmlArgs.NodeType = typeof(IModelColumn); } }
                                [VB.NET]
                                Public Sub ConvertXml(ByVal convertXmlArgs As ConvertXmlParameters) If GetType(IModelMemberViewItem).IsAssignableFrom(convertXmlArgs.NodeType) Then If convertXmlArgs.Values.Count > 0 AndAlso (Not convertXmlArgs.Values.ContainsKey("Id")) AndAlso convertXmlArgs.Values.ContainsKey("PropertyName") Then convertXmlArgs.Values.Add("Id", convertXmlArgs.Values("PropertyName")) End If End If If TypeOf convertXmlArgs.Node Is IModelClass Then If convertXmlArgs.XmlNodeName = "Member" Then Dim members As IModelBOModelClassMembers = (CType(convertXmlArgs.Node, IModelClass)).OwnMembers If members Is Nothing Then members = (CType(convertXmlArgs.Node, IModelClass)).AddNode(Of IModelBOModelClassMembers)("OwnMembers") End If convertXmlArgs.SubNode = members End If End If If convertXmlArgs.XmlNodeName = "NavigationItems" Then If convertXmlArgs.Values.ContainsKey("Current") AndAlso (Not convertXmlArgs.Values.ContainsKey("StartupNavigationItem")) Then convertXmlArgs.Values.Add("StartupNavigationItem", convertXmlArgs.Values("Current")) End If End If If convertXmlArgs.XmlNodeName = "ActionRef" Then convertXmlArgs.NodeType = GetType(IModelActionLink) End If If convertXmlArgs.XmlNodeName = "ColumnInfo" Then convertXmlArgs.NodeType = GetType(IModelColumn) End If End Sub

                                27. Using the Dictionary, DictionaryNode, DictionaryElement, DictionaryAttribute, DictionaryXmlReader and DictionaryXmlReader classes in custom scenarios non-related to the application model.
                                You could use these classes as wrappers to store and manage custom XML data in a typed manner.

                                PREVIOUSLY:

                                [C#]
                                public class DefaultsReader { public Dictionary Read(string name) { string resourceNamePrefix = GetType().Namespace + "." + name; System.Reflection.Assembly assembly = GetType().Assembly; DictionaryXmlReader reader = new DictionaryXmlReader(); DictionaryNode schemaNode = reader.ReadFromResource(assembly, resourceNamePrefix + ".Schema.xml"); DictionaryNode dataNode = reader.ReadFromResource(assembly, resourceNamePrefix + ".Data.xml"); return new Dictionary(dataNode, new Schema(schemaNode)); } } ... string defaultLanguage = DictionaryAttribute.DefaultLanguage;
                                [VB.NET]
                                Public Class DefaultsReader Public Function Read(ByVal name As String) As Dictionary Dim resourceNamePrefix As String = Me.GetType().Namespace + "." & name Dim [assembly] As System.Reflection.Assembly = Me.GetType().Assembly Dim reader As New DictionaryXmlReader() Dim schemaNode As DictionaryNode = reader.ReadFromResource([assembly], resourceNamePrefix & ".Schema.xml") Dim dataNode As DictionaryNode = reader.ReadFromResource([assembly], resourceNamePrefix & ".Data.xml") Return New Dictionary(dataNode, New Schema(schemaNode)) End Function End Class ... Dim defaultLanguage As String = DictionaryAttribute.DefaultLanguage

                                NOW:
                                These classes are not supported anymore, and you should either change your design (for example use the standard XmlSerializer and XmlDocument classes) or implement another solution based on the old 9.3 sources.
                                Instead of the string constants of the DictionaryAttribute class, use the corresponding constants of the DevExpress.ExpressApp.Utils.CaptionHelper class.
                                ========================================
                                28. Creating a custom store for application model differences.
                                Now you should implement a custom storage class inherited from the ModelDifferenceStore class. Refer to the  How to: Store the Application Model Differences in the Database and How to: Enable the Administrative UI for managing Users' Model Differences  articles for more details.
                                Previously, we have to descend it from the DictionaryDifferenceStore class.

                                PREVIOUSLY:

                                [C#]
                                public class UserStore : DictionaryDifferenceStore { protected override Dictionary LoadDifferenceCore(Schema schema) { ... } public override void SaveDifference(Dictionary diffDictionary) { ... } }
                                [VB.NET]
                                Public Class UserStore Inherits DictionaryDifferenceStore Protected Overrides Function LoadDifferenceCore(ByVal schema As Schema) As Dictionary ... End Function Public Overrides Sub SaveDifference(ByVal diffDictionary As Dictionary) ... End Sub End Class

                                NOW:

                                [C#]
                                public class UserStore :ModelDifferenceStore { protected override void Load(ModelApplicationBase model) { ... } public override void SaveDifference(ModelApplicationBase model) { ... } }
                                [VB.NET]
                                Public Class UserStore Inherits ModelDifferenceStore Protected Overrides Sub Load(ByVal model As ModelApplicationBase) ... End Sub Public Overrides Sub SaveDifference(ByVal model As ModelApplicationBase) ... End Sub End Class

                                =========================================
                                29. Adding new functionality to a property of an existing application model element.
                                Now it's not supported.
                                Previously, it was possible, for example:
                                - provide a list of possible values for an existing attribute of the application model element:

                                [XML]
                                <Attribute Name="ID" RefNodeName="{Saturn3.Common.DetailViewItemsRefNodeProvider}" /> <Attribute Name="EditorTypeName" RefNodeName="/Application/ListEditors/ListEditor"/>

                                - change the algorithm of calculating the default value of a property in the application model element:

                                [XML]
                                <Attribute Name="Caption" DefaultValueExpr="SourceNode=BOModel\Class\@Name=@ClassName; SourceAttribute=@ListCaption"/>

                                =========================================
                                30. Defining a custom validation rule.
                                Now, you need to explicitly declare an appropriate IXXXProperties interface for each of your custom rule classes. Additionally, you have to register them in the overridden CustomizeModelApplicationCreatorProperties method of your ModuleBase descendant:
                                For more details, see the RuleStringLengthComparison class in the FeatureCenter application (Documents\DevExpress 2010.1 Demos\eXpressApp Framework\FeatureCenter\CS\FeatureCenter.Module\Validation\CustomRuleObject.cs) and its registration in the
                                Documents\DevExpress 2010.1 Demos\eXpressApp Framework\FeatureCenter\CS\FeatureCenter.Module\Module.cs file.
                                =========================================
                                31. Specifying a caption displayed in the Model Editor for the application model element.
                                Now, you should mark the corresponding model interface with the DevExpress.ExpressApp.Model.ModelDisplayNameAttribute.
                                Previously, the name of the element was used as the caption displayed in the Model Editor for this element. Also, the obsolete DetailViewItemNameAttribute can be used to specify the captions of custom DetailViewItems.
                                =========================================
                                32. Specifying a default ListEditor for a certain type in code.
                                Now you should mark the ListEditor with the ListEditorAttribute and specify its isDefault parameter. Alternatively, you can implement a ModelNodesGeneratorUpdater for the ListView, as shown in the 20th point.
                                Previously, it was possible to override the UpdateModel method and use the generic ListEditorForClassCustomizer class.

                                PREVIOUSLY:

                                [C#]
                                public override void UpdateModel(Dictionary model) { base.UpdateModel(model); ListEditorForClassCustomizer<SchedulerListEditor> listEditorForClassCustomizer = new ListEditorForClassCustomizer<SchedulerListEditor>(typeof(IEvent)); listEditorForClassCustomizer.Customize(model); }
                                [VB.NET]
                                Public Overrides Sub UpdateModel(ByVal model As Dictionary) MyBase.UpdateModel(model) Dim listEditorForClassCustomizer As New ListEditorForClassCustomizer(Of SchedulerListEditor)(GetType(IEvent)) listEditorForClassCustomizer.Customize(model) End Sub

                                =========================================