Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Matt Taylor 873 posts 2086 karma points
    Jul 24, 2020 @ 11:50
    Matt Taylor
    0

    The Models Builder properties are read only so how can I set them?

    The properties created by the Models Builder are all read only. How can make these properties settable?

    Maybe it's a silly question but I want to be able to manipulate the values of some Models Builder object properties in my code and pass the objects around rather than creating extra variables to hold the manipulated values.

    I hope that makes sense.

    Thanks,

    Matt

  • Daniel Rogers 140 posts 718 karma points
    Jul 02, 2021 @ 01:43
    Daniel Rogers
    0

    How have you got on with this. I also are trying to use a properties in code so as I don't have to duplicate them in code. Buy them=y are all read only.

  • Erik Eelman 81 posts 321 karma points
    Jul 02, 2021 @ 08:11
    Erik Eelman
    0

    Hi Matt,

    You can create a partial class for the modelsbuilder object and override the properties you want to manipulate with ImplementPropertyType decoration.

    You can use something like this:

        public partial class DetailPage 
        {
            [ImplementPropertyType("relatedPages")]
            public IEnumerable<IPublishedContent> RelatedPages => RelatedContentComposition.GetRelatedPages(this); 
        }
    

    Does this help?

    Erik

  • Daniel Rogers 140 posts 718 karma points
    Jul 02, 2021 @ 12:20
    Daniel Rogers
    0

    Hi Erik sort of just trying to relate it back to my situation.

    My Modul builder deck looks like this

    //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------

    using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Web; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web; using Umbraco.ModelsBuilder; using Umbraco.ModelsBuilder.Umbraco;

    namespace IBDStarterKit.Models { ///

    Window Tiles [PublishedModel("IBDWindowTilesComponent")] public partial class IbdWindowTilesComponent : PublishedContentModel { // helpers

    pragma warning disable 0109 // new is redundant

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        public new const string ModelTypeAlias = "IBD_Window_Tiles_Component";
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        public new const PublishedItemType ModelItemType = PublishedItemType.Content;
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        public new static IPublishedContentType GetModelContentType()
            => PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias);
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        public static IPublishedPropertyType GetModelPropertyType<TValue>(Expression<Func<Ibd_Window_Tiles_Component, TValue>> selector)
            => PublishedModelUtility.GetModelPropertyType(GetModelContentType(), selector);
    

    pragma warning restore 0109

        // ctor
        public Ibd_Window_Tiles_Component(IPublishedContent content)
            : base(content)
        { }
    
        // properties
    
        ///<summary>
        /// Heading
        ///</summary>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        [ImplementPropertyType("windowHeading")]
        public string WindowHeading => this.Value<string>("windowHeading");
    
        ///<summary>
        /// Tiles
        ///</summary>
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
        [ImplementPropertyType("windowTiles")]
        public IEnumerable<Ibd_Window_Tile> WindowTiles => this.Value<IEnumerable<Ibd_Window_Tile>>("windowTiles");
    }
    

    So I have added this declaration

    public partial class Ibd_Window_Component {
        [ImplementPropertyType("windowTiles")]
        public IEnumerable<Ibd_Window_Tile> WindowTiles => RelatedContentComposition.GetRelatedPages(this);
    }
    

    But its not quit there RelatedContentComposition is underlined in red.

  • Erik Eelman 81 posts 321 karma points
    Jul 02, 2021 @ 12:38
    Erik Eelman
    0

    Hi Daniel,

    You need to add your custom implementation in that place, you just copied my custom implementation ;)

    You can do something like this:

     [ImplementPropertyType("windowTiles")]
        public IEnumerable<Ibd_Window_Tile> WindowTiles
        {
            get
            {
                // Do custom stuff here
    
                // This is what the basic modelsbuilder returns
                return this.Value<IEnumerable<Ibd_Window_Tile>>("windowTiles");
            }
        }
    

    I suggest you create a new file with the partial class in so it doesn't get overwriten when you rebuild your modelsbuilder models.

    Then you can rebuild your UmbracoModels (the basic implementation in the generated models file will then disapear)

  • Daniel Rogers 140 posts 718 karma points
    Jul 05, 2021 @ 02:15
    Daniel Rogers
    0

    Thanks Eric I understand that and I have my partial declaration in an other file etc.

    And I have done this before to add new variables to the class. But they are new variables. not modifying the old ones so the extent of my knowledge there is to do something like

    public partial class Ibd_Window_Component { // Where this is my doc type 
        public string AdditonalString {get;set;}
    }
    

    But this is not what Im trying to do.

    I want to use it like this in a controller for setting my the content of the model to pass to a partial view

    So this is the code I use at present that is a direct duplication of the doctypes. Which I are trying to get away from.

            Ibd_Window_Tiles Model = new Ibd_Window_Tiles();
    
            Model.WindowHeading = "Hello";
            Model.WindowTiles = new List<Ibd_Window_Tile>();
            ...........
            Ibd_Window_Tile Tile= new Ibd_Window_Tile();
            Model.WindowTiles.Appent(Tile);
    

    etc.

    the problem is that if I use the doctype version IbdWindowTiles_Componet etc then the error is that WindowHeading is read only.

    Is my question is still, I know I need to put something in the // Do something here.

    But I don't understand and cant find any examples of what to put here.

    There must be a way of doing this without duplicating code.

  • Erik Eelman 81 posts 321 karma points
    Jul 07, 2021 @ 08:23
    Erik Eelman
    0

    Hi Daniel,

    Perhaps I misunderstand you, but is it correct that you don't get the tile content from Umbraco (since you are populating it in code)?

    If this is the case, why not create a custom viewmodel and pass this model to the partial view?

    With the override example you can return whatever you want, for example:

    [ImplementPropertyType("windowTiles")]
    public IEnumerable<YourCustomModel> WindowTiles
    {
        get
        {
            // Do custom stuff here
            return new List<YourCustomModel> {
                new YourCustomModel {
                    Title =  "This is the title"
                }
            };
        }
    }
    
  • Daniel Rogers 140 posts 718 karma points
    Jul 07, 2021 @ 12:42
    Daniel Rogers
    0

    Thanks Erik for the conversation. Please bare with me.

    So the majority of the time I want to populate the data from the CMS environment. But I also have an instance where I want to populate it from the controller on code and pass it back to the partial view.

    So the at present I have a duplicate model's coded to match the doctype's (models builder model).

    Then I have duplicate partial views dependant on if it is the coded model or the doctype.

    So I really want to eliminate the coded model so as I can populate a doctype in code then pass it to the same partial view.

  • Matt Taylor 873 posts 2086 karma points
    Jul 07, 2021 @ 13:14
    Matt Taylor
    0

    Hello Erik,

    Yes you can implement your own version of the property in a partial class like you have suggested but you can't set the change the value later on in code.

    What I have done is duplicate the properties with a get/set so I might have

    [ImplementPropertyType("title")]
            public string Title => this.Value<string>("title");
    

    and then I'll create another in my partial class that I can change

    public string DisplayTitle { get; set; }
    
Please Sign in or register to post replies

Write your reply to:

Draft