{"id":3284,"date":"2020-01-28T13:17:52","date_gmt":"2020-01-28T12:17:52","guid":{"rendered":"https:\/\/solidt.eu\/site\/?p=3284"},"modified":"2025-06-18T16:03:36","modified_gmt":"2025-06-18T15:03:36","slug":"devexpress-xaf-xpo","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/devexpress-xaf-xpo\/","title":{"rendered":"DevExpress XAF XPO"},"content":{"rendered":"\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using DevExpress.ExpressApp.Model;\nusing DevExpress.Persistent.Base;\nusing DevExpress.Persistent.Validation;\nusing DevExpress.Xpo;\nusing MRP.Common;\nusing System.ComponentModel;\n\nnamespace MRP.Model.Masterdata\n{\n    [NavigationItem(\"Stamgegevens\")]\n    [CreatableItem(true)]\n    [DefaultProperty(\"ProductSampleCustomerRetentionPeriod\")]\n    [ModelDefault(\"Caption\", \"Product bewaartermijn per klant\")]\n    public class ProductSampleCustomerRetentionPeriod : MRPBaseObject\n    {\n        public ProductSampleCustomerRetentionPeriod(Session session) : base(session) { }\n\n        private Company _company;\n        [Association(\"Company-ProductSampleCustomerRetentionPeriod\")]\n        [ModelDefault(\"Caption\", \"Bedrijf\")]\n        [RuleRequiredField(\"RuleRequiredField for ProductSampleCustomerRetentionPeriod.Company\", DefaultContexts.Save, \"Bedrijf is een verplicht veld.\")]\n        [VisibleInDetailView(true)]\n        public Company Company\n        {\n            get => _company;\n            set => SetPropertyValue(nameof(Company), ref _company, value);\n        }\n\n        private Customer _customer;\n        [Association(\"Customer-ProductSampleCustomerRetentionPeriod\")]\n        [ModelDefault(\"Caption\", \"Klant\")]\n        [RuleRequiredField(\"RuleRequiredField for ProductSampleCustomerRetentionPeriod.Customer\", DefaultContexts.Save, \"Klant is een verplicht veld.\")]\n        [VisibleInDetailView(true)]\n        public Customer Customer\n        {\n            get => _customer;\n            set => SetPropertyValue(nameof(Customer), ref _customer, value);\n        }\n\n        private ProductSample _productSample;\n        [Association(\"ProductSample-ProductSampleCustomerRetentionPeriod\")]\n        [ModelDefault(\"Caption\", \"Product monster\")]\n        [DataSourceCriteria(\"Product.Company.Oid == '@This.Company.Oid'\")]\n        [RuleRequiredField(\"RuleRequiredField for ProductSampleCustomerRetentionPeriod.ProductSample\", DefaultContexts.Save, \"'Product monster' is een verplicht veld.\")]\n        [VisibleInDetailView(true)]\n        public ProductSample ProductSample\n        {\n            get => _productSample;\n            set => SetPropertyValue(nameof(ProductSample), ref _productSample, value);\n        }\n\n        private int? _retentionPeriod;\n        [ModelDefault(\"Caption\", \"Bewaartermijn\")]\n        [ModelDefault(\"ToolTip\", \"Bewaartermijn van de monster analyse in dagen.\\nHiervoor wordt de maximale waarde van de bij het product, de klant of het type monster ingestelde bewaartermijn.\")]\n        [RuleValueComparison(\"RuleValueComparison for ProductSampleCustomerRetentionPeriod.RetentionPeriod\", DefaultContexts.Save, ValueComparisonType.GreaterThan, 0, \"De bewaartermijn moet groter dan nul zijn\", SkipNullOrEmptyValues = true)]\n        public int? RetentionPeriod\n        {\n            get => _retentionPeriod;\n            set => SetPropertyValue(nameof(RetentionPeriod), ref _retentionPeriod, value);\n        }\n    }\n}\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">        [Association(\"Company-ProductSampleCustomerRetentionPeriod\"), Aggregated]\n        [ModelDefault(\"Caption\", \"Bewaartermijnen per klant\")]\n        public XPCollection&lt;ProductSampleCustomerRetentionPeriod> ProductSampleCustomerRetentionPeriods => GetCollection&lt;ProductSampleCustomerRetentionPeriod>(nameof(ProductSampleCustomerRetentionPeriods));<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ Available Attributes\n\n[NavigationItem(\"Stamgegevens\")]\n[ImageName(\"EmbeddedResourceName\")]\n[CreatableItem(true)]\n[CreatableItem(false)] \/\/ Hides new item buttons\n[DefaultProperty(\"ProductSampleCustomerRetentionPeriod\")]\n[LookupEditorMode(LookupEditorMode.AllItemsWithSearch)]\n\n[DomainComponent] \/\/ Use for non persistent domain model, used in views\n[NonPersistent]\n[Persistent]\n[Persistent(\"FieldNameOrTableName\")]\n\n[Association(\"Company-ProductSampleCustomerRetentionPeriod\")]\n[RuleRequiredField(\"RuleRequiredField for ProductSampleCustomerRetentionPeriod.Company\", DefaultContexts.Save, \"Bedrijf is een verplicht veld.\")]\n\n[Browsable(false)]\n[VisibleInListView(false)]\n[VisibleInDetailView(false)]\n\n[Key] \/\/ Field is Key (Primary Index)\n[Key(true)] \/\/ Field is Key (Primary Index)\n[NoForeignKey] \/\/ Disable foreign key generation on a class member\n[Size(300)] \/\/ Field size\/length\n[Size(SizeAttribute.Unlimited)] \/\/ Blob\/Varchar(MAX) fields\n[DbType(\"Time\")] \/\/ Custom Database Type\n[ValueConverter(typeof(TimeSpanToPostgreSQLTimeValueConverter))] \/\/ Convert to database type\n[NullValue(\"\")] \/\/ When value is null, store it as given\n[Indexed]\n[Indexed(Unique = true)] \/\/ Field is unique indexed\n[Delayed]\n\/\/ Indicates that the property's value should not be loaded when a persistent object\n\/\/ is being loaded. The property will be loaded the first time it is accessed.\n[ReadOnly(true)]\n[Editable(false)]\n[MapInheritance(MapInheritanceType.ParentTable)] \/\/ Specifies the type of object-relational inheritance mapping for the class.\n\n[Persistent(\"Oid\"), Key(true), Browsable(false), MemberDesignTimeVisibility(false)]\n[PersistentAlias(nameof(_oid))]\n\n\n[DesignerCategory(\"\")] \/\/ \n[ImmediatePostData]\n[DataSourceProperty(\"VestigingLookup\")]\n\n[ModelDefault(\"ReadOnly\", \"True\")]\n[ModelDefault(\"LookupEditorMode\", \"AllItemsWithSearch\")]\n[ModelDefault(\"RowCount\", \"1\")]\n[ModelDefault(\"ToolTip\", \"Als dit vinkje aan staat, verwijst de weegbrug applicatie de vrachtwagen naar dit dok als de laadbon bulk artikelen bevat.\")]\n[ModelDefault(\"Caption\", \"Laadbon ladingen\")]\n[ModelDefault(\"Index\", \"0\")]\n[ModelDefault(\"EditMask\", \"dd-MM-yyyy HH:mm\")]\n[ModelDefault(\"EditMask\", \"##########\")]\n[ModelDefault(\"Index\", \"7\"), Size(300)]\n[ModelDefault(\"Index\", \"12\"), ImmediatePostData, ModelDefault(\"ReadOnly\", \"True\"), VisibleInListView(false), VisibleInLookupListView(false)]\n[ModelDefault(\"AllowEdit\", \"False\")]\n[ModelDefault(\"DisplayFormat\", \"HH:mm\")]\n[ModelDefault(\"DisplayFormat\", \"{0:g}\")]\n[ModelDefault(\"DisplayFormat\", \"###,##0.00\")]\n[ModelDefault(\"DisplayFormat\", \"##########\"), ModelDefault(\"EditMask\", \"##########\")]\n[ModelDefault(\"DisplayFormat\", \"{0:#,##0.00}\"), ModelDefault(\"EditMask\", \"#,##0.00\")]\n\/\/?\n[Custom(\"DisplayFormat\", \"{0:#,###,##0.00}\")] \/\/ DevExpress.Xpo.CustomAttribute\n\n[RuleFromIPropertyValueValidator(\"RuleFromIPropertyValueValidator for Losplaats.Vestiging\", DefaultContexts.Save, \"U heeft geen rechten voor deze vestiging.\", SkipNullOrEmptyValues = false)]\nbool IPropertyValueValidator.IsPropertyValueValid(string property, ref string errorMessage)\n{\n    return true;\n}\n\n[XafDisplayName(\"Te verzenden\")]\n[DXDisplayName(typeof(ConsumptieInkoopContract), \"InkoopSoort Display Name\")]\n\n[ListEditor(typeof(Levering), false)]\n[ListEditor(typeof(DummyPersistentObject))]\n[ToolboxItem(false)]\n\n[Appearance(\"AppearanceAttribute for VerkoopLaadreferentie\", AppearanceItemType.ViewItem, \"ShowVerkoopLaadreferentieInListview = True\", TargetItems = \"*\", Context = \"ListView\", BackColor = \"Coral\")]\n\n[Localizable(true)]\n[Category(\"Format\")]\n[Description(\"Specifies the text that will be displayed in the Validation Error window when the Validation Rule is broken.\")]\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ To enable sorting, filtering and grouping (in server-side SQL query mode) use a persistent alias\n[PersistentAlias(\"Artikel.Code\")]\npublic string ArtikelCode => ReferenceEquals(Artikel, null) ? \"\" : Artikel.Code;\n\n[PersistentAlias(\"Artikel.Artikelgroep.Omschrijving\")]\npublic string Artikelgroep => ReferenceEquals(Artikel, null) ? \"\" : ReferenceEquals(Artikel.Artikelgroep, null) ? \"\" : Artikel.Artikelgroep.Omschrijving;\n\n[PersistentAlias(\"Tarief.Tariefsoort\")]\npublic string Tariefsoort => ReferenceEquals(Tarief, null) ? \"\" : Tarief.Tariefsoort;\n\n\n\/\/ When a field is not immediately updated or the save button is unavailable use [ImmediatePostData] attribute on e.g. a [NonPersistend] property\n[ImmediatePostData]\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Artikel _grondmonsterkosten;\n[VisibleInListView(false), VisibleInLookupListView(false)]\n[DataSourceProperty(\"ArtikelLookup\")]\n[ModelDefault(\"LookupEditorMode\", \"AllItemsWithSearch\")]\npublic Artikel Grondmonsterkosten\n{\n\tget { return (_grondmonsterkosten); }\n\tset { SetPropertyValue(nameof(Grondmonsterkosten), ref _grondmonsterkosten, value); }\n}\n\nXPCollection&lt;Artikel> _artikellookup;\n[Browsable(false)]\npublic XPCollection&lt;Artikel> ArtikelLookup\n{\n\tget\n\t{\n\t\t_artikellookup?.Reload();\n\t\t_artikellookup = new XPCollection&lt;Artikel>(Session)\n\t\t{\n\t\t\tCriteria = new BinaryOperator(nameof(Artikel.MultiversAdministratie), this)\n\t\t};\n\t\treturn _artikellookup;\n\t}\n}<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace DevExpress.Xpo\n{\n    [MemberDesignTimeVisibility(false)]\n    [NonPersistent]\n    [OptimisticLocking(true)]\n    public abstract class XPBaseObject : PersistentBase, IEditableObject, ICustomTypeDescriptor, IComparable, IXPReceiveOnChangedFromXPPropertyDescriptor\n    {\n\t\t\/\/ From PersistentBase\n\t\tpublic bool IsLoading { get; }\n        public bool IsDeleted { get; }\n\t\tprotected bool IsSaving { get; }\n\t\t\/\/ From PersistentBase: Events to override\n\t\tprotected virtual void OnChanged(string propertyName, object oldValue, object newValue);\n\t\tprotected virtual void OnDeleted();\n\t\tprotected virtual void OnDeleting();\n\t\tprotected virtual void OnLoaded();\n\t\tprotected virtual void OnLoading();\n\t\tprotected virtual void OnSaved();\n\t\tprotected virtual void OnSaving();\n\t\t\n\t\t\/\/ Other\n        public static bool AutoSaveOnEndEdit;\n        protected XPBaseObject();\n        protected XPBaseObject(Session session);\n        protected XPBaseObject(Session session, XPClassInfo classInfo);\n        [Browsable(false)]\n        public object This { get; }\n        [Browsable(false)]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MemberDesignTimeVisibility(false)]\n        [Obsolete(\"Use the XPBaseObject.IsLoading property instead.\", true)]\n        public bool Loading { get; }\n        public event ObjectChangeEventHandler Changed;\n        public static void AddChangedEventHandler(object persistentObject, ObjectChangeEventHandler handler);\n        public static void AddChangedEventHandler(object persistentObject, IObjectChange handler);\n        public static void RaiseChangedEvent(object persistentObject, ObjectChangeEventArgs args);\n        public static void RemoveChangedEventHandler(object persistentObject, ObjectChangeEventHandler handler);\n        public static void RemoveChangedEventHandler(object persistentObject, IObjectChange handler);\n        public void Delete();\n        public object Evaluate(CriteriaOperator expression);\n        public object Evaluate(string expression);\n        public object EvaluateAlias(string memberName);\n        public bool Fit(string condition);\n        public bool Fit(CriteriaOperator condition);\n        public object GetMemberValue(string propertyName);\n        public void Reload();\n        public void Save();\n        public void SetMemberValue(string propertyName, object newValue);\n        protected virtual void AfterChangeByXPPropertyDescriptor();\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Use the XPBaseObject.OnLoaded method instead.\", true)]\n        protected virtual void AfterLoad();\n        protected virtual void BeforeChangeByXPPropertyDescriptor();\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Use the XPBaseObject.OnSaving method instead.\", true)]\n        protected virtual void BeforeSave();\n        protected virtual void BeginEdit();\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Use the XPBaseObject.OnLoading method instead.\", true)]\n        protected virtual void BeginLoad();\n        protected virtual void CancelEdit();\n        protected virtual XPCollection&lt;T> CreateCollection&lt;T>(XPMemberInfo property);\n        protected virtual void DoEndEditAction();\n        protected virtual void EndEdit();\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Use the XPBaseObject.OnLoaded method instead.\", true)]\n        protected virtual void EndLoad();\n        protected virtual void FireChangedByCustomPropertyStore(XPMemberInfo member, object oldValue, object newValue);\n        protected virtual void FireChangedByXPPropertyDescriptor(string memberName);\n        protected XPCollection GetCollection(string propertyName);\n        protected XPCollection&lt;T> GetCollection&lt;T>(string propertyName) where T : class;\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [Obsolete(\"Use GetPropertyValue&lt;T> instead\", true)]\n        protected object GetPropertyValueWithDefault(string propertyName, object defaultValue);\n        protected override void Invalidate(bool disposing);\n        protected void OnChanged(string propertyName);\n        protected void OnChanged();\n        protected override void OnChanged(string propertyName, object oldValue, object newValue);\n        protected override void OnDeleting();\n        protected override void OnLoaded();\n        protected override void OnSaved();\n        protected void RaiseChangeEvent(ObjectChangeEventArgs args);\n        protected override void TriggerObjectChanged(ObjectChangeEventArgs args);\n    }\n}<\/pre>\n\n\n\n<p>In-direct linked collection:<\/p>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">private XPCollection&lt;MyItem> _Items;\n[ModelDefault(\"Caption\", \"Linked MyItems\")]\n[ModelDefault(\"ToolTip\", \"List of items linked to this item either directly or via the subitems.\")]\npublic XPCollection&lt;MyItem> Items\n{\n    get \n    { \n        if (_Items == null)\n        {\n            _Items = new XPCollection&lt;MyItem>(\n                PersistentCriteriaEvaluationBehavior.InTransaction, \n                Session, \n                new GroupOperator(GroupOperatorType.Or,\n                new InOperator(nameof(MyItem.Name), LinkedSubItems),\n                new InOperator(nameof(MyItem.Oid), LinkedItems)));\n        }\n\n        return _Items;\n    }\n}\n<\/pre><\/div>\n\n\n\n<p>Example of a non-persistent class<\/p>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">[DomainComponent]\n[DefaultClassOptions]\n[CreatableItem(false)]\n[NavigationItem(\"MenuCategoryName\")]\n[ModelDefault(\"Caption\", \"MenuItemName\")]\n[ImageName(\"MenuImageName\")]\npublic class NonPersistentOplossingListViewItem\n{\n    public NonPersistentOplossingListViewItem()\n    {\n    }\n\n    [Browsable(false)]\n    public Guid? Oid { get; set; }\n\n    public string Titel { get; set; }\n\n    public string TrefWoorden { get; set; }\n\n    [ModelDefault(\"Caption\", \"Gekoppelde items's\")]\n    public string ItemsAsString => string.Join(\", \", GekoppeldeItems.Select(x => $\"{x.CompleteCode} {x.Omschrijving}\"));\n\n    [ModelDefault(\"DisplayFormat\", \"{0:g}\")]\n    [ModelDefault(\"EditMask\", \"g\")]\n    [ModelDefault(\"AllowEdit\", \"false\")]\n    public DateTime Aanmaakdatum { get; set; }\n    public Oplossingstype? Type { get; set; }\n    public XPCollection&lt;Configuratieitem> GekoppeldeItems { get; set; }\n}<\/pre><\/div>\n\n\n\n<p>Save object property without locking<\/p>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">private static void ToggleWaitingForReactionWithoutLocking(IDataLayer dataLayer, CommunicatieItem ci)\n{\n    ITicket ticket = LinqHelper.Select&lt;ITicket>(ci.Call, ci.RequestForChange, ci.Change).FirstOrDefault(x => x != null);\n    if (ticket == null) return;\n    using (var uow = new UnitOfWork(dataLayer))\n    {\n        uow.LockingOption = LockingOption.None;\n        var obj = (ITicket)uow.GetObjectByKey(ticket.GetType(), ticket.Oid);\n        obj.WaitingForReaction = false;\n        uow.CommitChanges();\n    }\n}\n\/\/ Use:\nToggleWaitingForReactionWithoutLocking(this.Session.DataLayer)\n<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In-direct linked collection: Example of a non-persistent class Save object property without locking<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3284","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/3284","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=3284"}],"version-history":[{"count":23,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/3284\/revisions"}],"predecessor-version":[{"id":9571,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/3284\/revisions\/9571"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=3284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=3284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=3284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}