+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Controlling fields in Module List View

Controlling fields in Module List View

17 posts, 0 answered
  1. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    11 Dec 2010
    Link to this post
    Hi,

    I have a module which stores a metafield called UserID. I have updated the DataBindGrid Javascript function that is responsible for returning each of the metafields I want displayed on the view. My list view now shows UserID.

    function DataBindGrid(currentPageIndex, pageSize, sortExpressionsAsSQL, filterExpressionsAsSQL) {
                    var requiredMetaFields = ['Name', 'UserID', 'PublicationFrequency', 'AudioLibraryItemID'];
                    var cultureInfoField = document.getElementById('<%= cultureInfoField.ClientID %>');
                    Telerik.Cms.Engine.Services.ContentService.GetContentItems(currentPageIndex * pageSize, pageSize,
                    sortExpressionsAsSQL, filterExpressionsAsSQL, requiredMetaFields, cultureInfoField.value, dataProviderName, updateGrid, OnFailed);
                }

    However, I want to run a query against the database to get the Name of the User, based on the UserID field. In C# this is easy enough:

    //get the user details
                MembershipUser oUser = Membership.GetUser("userID");
     
                //populate input fields
                this.oFirstNameTextBox.Text = ProfileBase.Create(oUser.UserName).GetPropertyValue("FirstName").ToString();
                this.oLastNameTextBox.Text = ProfileBase.Create(oUser.UserName).GetPropertyValue("LastName").ToString();

    But how can i do this within the datagrid that is used to display each of the content items?

    Thanks
    higgsy
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    11 Dec 2010
    Link to this post
    Hi higgsy,

    You have to create a custom web service and use it instead of the default one. You can find a sample code here.

    All the best,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    11 Dec 2010
    Link to this post
    Hi Ivan,

    I didnt expect a response  back on a saturday! Good stuff!

    Ok - i'll try that suggestion - before I do so, there is a comment on the blog that says the code deosnt deal with record paging. is that correct?

    Thanks
    higgsy
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    11 Dec 2010
    Link to this post
    Hi higgsy,

    By default we pass 50 items to GetContent method in the web service and the paging is handler by the RadGrid. The GetContent makes a query only for the items you requested.

    Regards,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  5. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    11 Dec 2010
    Link to this post
    Thanks Ivan - I'll give it a try.
  6. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    04 Jan 2011
    Link to this post
    Hi Ivan,

    I've finally got round to creating a web service to return the fields I want to see in my module's listview.

    However I'm getting a javascript error here:

    function DataBindGrid() {
                    App_Code.Modules.Members.MembersModule.Services.MembersContentService.GetMembers(dataProviderName, updateGrid, OnFailed);
                }

    The error is App_Code is not defined. Do I need to register my web service somewhere? Or do i need to call the url instead from js?

    Thanks
    higgsy
  7. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    04 Jan 2011
    Link to this post
    Hello higgsy,

    You should add a reference to your service inside Sitefinity/Admin/Admin.master.cs

    protected override void OnPreRender(EventArgs e)
      {
          base.OnPreRender(e);
     
          ScriptManager sm = ScriptManager.GetCurrent(this.Page);
          ServiceReference reference = new ServiceReference("~/Sitefinity/Admin/Services/MyService.asmx");
          reference.InlineScript = true;
          sm.Services.Add(reference);
     
     
      }


    Regards,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    04 Jan 2011
    Link to this post
    Hi Ivan,

    That has got me one step further, however I now get the js error:

    {"Message":"Unable to cast object of type \u0027Telerik.Cms.Engine.Data.CmsContentBase\u0027 to type \u0027App_Code.Modules.Members.MembersModule.IMember\u0027.","StackTrace":"   at App_Code.Modules.Members.MembersModule.Services.MembersContentService.GetMembers(ContentManager oContentMgr) in d:\\tnf\\www\\App_Code\\Modules\\Members\\Services\\MembersContentService.cs:line 47\r\n   at App_Code.Modules.Members.MembersModule.Services.MembersContentService.GetMembers(String providerName) in d:\\tnf\\www\\App_Code\\Modules\\Members\\Services\\MembersContentService.cs:line 38","ExceptionType":"System.InvalidCastException"}

    The code for my web service is: (I have highlighted lines 38 and 47)

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Script.Services;
    using System.Web.Services;
    using Telerik.Web.UI;
    using Telerik.Cms;
    using Telerik.Cms.Engine;
     
    /// <summary>
    /// Summary description for MembersContentService
    /// </summary>
    ///
    namespace App_Code.Modules.Members.MembersModule.Services
    {
     
        [ScriptService]
        public class MembersContentService {
     
            #region Fields
     
            private string _providerName;
     
            #endregion
     
            /// <summary>
            /// Gets or sets the provider name.
            /// </summary>
            public string ProviderName {
                get { return this._providerName; }
            }
     
            [WebMethod]
            public GridBindingData GetMembers(string providerName) {
     
                return this.GetMembers(new ContentManager(providerName));
            }
     
            public GridBindingData GetMembers(ContentManager oContentMgr) {
     
                IList oContentItems = oContentMgr.GetContent();
     
                int intCount = oContentItems.Count;
                List<object> dataList = new List<object>(intCount);
                foreach (IMember oMember in oContentItems) {
                    dataList.Add(new SimpleMemberItem(oMember));
                }
     
                return new GridBindingData(dataList, intCount);
     
            }
     
        }
     
    }

    My Member Interface:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
     
    namespace App_Code.Modules.Members.MembersModule {
     
        /// <summary>
        /// Summary description for IMember
        /// </summary>
        public interface IMember {
     
            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            /// <value>The first name.</value>
            string Name { get; set; }
     
     
        }
     
    }

    And my SimpleMemberItem class:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
     
    namespace App_Code.Modules.Members.MembersModule {
     
        /// <summary>
        /// Summary description for SimpleMemberItem
        /// </summary>
        public class SimpleMemberItem {
     
            #region Fields
     
            private string _Name;
     
            #endregion
     
     
            public SimpleMemberItem(IMember oMember) {
                this.Name = oMember.Name;
            }
     
     
            /// <summary>
            /// Gets or sets the first name.
            /// </summary>
            /// <value>The first name.</value>
            public string Name {
                get {
                    return this._Name;
                }
                set {
                    this._Name = value;
                }
            }
     
     
        }
     
    }

    The only difference seems to be that I am calling IList oContentItems = oContentMgr.GetContent(), but I dont see how else I can get the content I require from my module.

    Thanks
    higgsy
  9. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    04 Jan 2011
    Link to this post
    Hello higgsy,

    The problem is that oContentMgr.GetContent() returns IList of IContent items, but you are trying to cast these IContent items to IMember objects.
    You should create a new list of  type IMember and for each IContent you have to create IMember item and add it to your list of  type IMember. Then you have to return this list in the method GetMembers. The signature of the GridBindingData is public GridBindingData(List<object> data, int count);

    Best wishes,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  10. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    05 Jan 2011
    Link to this post
    Hi Ivan,

    Thanks for your response.

    I realise why I am getting the cast error, but I dont understand how to:

    - Call ContentManager.GetContent();
    - Loop through each record and create an instance of my IMember interface
    - Add that instance of the IMember interface to the List<IMember>

    I have looked at the samples module, and the code is very similar however the code is not using the ContentManager anywhere, it is using a method called GetContacts:

    /// <summary>
    /// Simplified version of GetContacts implementation. For sake of example only.
    /// </summary>
    /// <returns>List of IContact objects</returns>
    public override IList GetContacts()
    {
        Contacts query = new Contacts();
        query.LoadAll();
        return query;
    }
     
    public override IList GetContacts(string firstLetterFilter)
    {
        IList allContacts = this.GetContacts();
        List<IContact> filteredContacts = new List<IContact>();
        foreach (IContact contact in allContacts)
        {
            if (contact.LastName.StartsWith(firstLetterFilter, StringComparison.OrdinalIgnoreCase))
                filteredContacts.Add(contact);
        }
        return filteredContacts;
    }

    It looks like the first implementation of GetContacts is using a data layer to go off and query the database. Surely I don't need to do this?

    Can't I just create a class which inherits from my interface? And then pass the class to the simplememberitem?

    Thanks
    higgsy
  11. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    05 Jan 2011
    Link to this post
    Ivan,

    As an update, I have now got the data returning, however it is not showing in the radgrid. There is a JS error:

    dataItem[collectionName] is undefined

    Which points to the line 75:

    function TemplateSet(id){
    57 this.ID = id;
    58 this.Templates = [];
    59 this.Pattern = /\{#\w+([.]\w+)?#}/g;
    60}
    61TemplateSet.prototype.Replace = function(templateName, dataItem){
    62 var template = this.Templates[templateName];
    63 if (template == undefined){
    64 return null;
    65 }
    66 var matches = template.match(this.Pattern);
    67 if(matches != null)
    68 {
    69 for (var j = 0; j < matches.length; j++) {
    70 var name = matches[j];
    71 name = name.slice(2, name.length - 2);
    72 if(name.indexOf('.') > -1) {
    73 var collectionName = name.split('.')[0];
    74 var collectionItemKey = name.split('.')[1];
    75 template = template.replace(matches[j], dataItem[collectionName][collectionItemKey]);
    76 }
    77 else {
    78 template = template.replace(matches[j], dataItem[name]);
    79 }
    80 }
    81 }
    82 return template;
    83}

    Is it obvious whats happening?

    Thanks
    higgsy

  12. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    05 Jan 2011
    Link to this post
    Hello higgsy,

    The problem is somewhere in the template you use. It cannot be parsed correctly. There is something wrong in the template you have your your view or the data you are returning from the web service is not GridBindingData.

    Regards,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  13. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    06 Jan 2011
    Link to this post
    Hi Ivan,

    I have got it all working, however I have two final hurdles. I have 1465 records to return from my web service, so I need to return them in batches of 50 for example. That itself isnt a major issue:

    function DataBindGrid(currentPageIndex, pageSize) {
        App_Code.Modules.Members.MembersModule.Services.MembersContentService.GetMembers(currentPageIndex * pageSize, pageSize, dataProviderName, updateGrid, OnFailed);
    }

    And my web service:
    IList oContentItems = oContentMgr.GetContent(pageIndex, pageSize);

    The problem is the pager at the bottom of the list then only shows 1 pages, whereas there should be about 30 pages. I can't find any code in the standard listviewitem.ascx controls that updates the pager with the number of pages, how can I do this?

    Finally, when a user clicks on the headertext of a column I need to provide sorting. How do I get the value they have clicked on?

    Thanks
    higgsy
  14. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    06 Jan 2011
    Link to this post
    Ivan,

    Not to worry, I have discovered that the "num" that is returned in the GridDataBinding needs to represent the total number of content items, not that which is actually being returned. It was only possible to find this out by refactoring Telerik.cms.engine as the code example doesnt explain this.

    If it would be useful i'll put a full blog article together on it?

    higgsy
  15. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    06 Jan 2011
    Link to this post
    Hello higgsy,

    Generally this is a standard implementation where you have two parameters in a given overload. In our base methods of ContentManager we have several overloads for GetContent where you can pass the start index and end index which shows how many items you want to retrieve from the database. The same thing is if you use LINQ where you have Take() and Skip() which are commonly used with Grid scenarios.

    Kind regards,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  16. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    06 Jan 2011
    Link to this post
    Ivan,

    One last thing. In my clienttemplate I need to place two link buttons, like so:

    <telerik:ClientTemplatesHolder id="GridTemplates" runat="server">
        <telerik:ClientTemplate Name="AccountStatus" runat="server">
            {#AccountStatus#}
            (
            <asp:LinkButton runat="server" ID="lnkbtnEnableUser" Text="Enable" ToolTip="EnableUser" CommandName="EnableUser" CommandArgument="{#UserID#}"></asp:LinkButton> /
            <asp:LinkButton runat="server" ID="lnkbtnDisableUser" Text="Disable" ToolTip="DisableUser" ></asp:LinkButton>
            )
        </telerik:ClientTemplate>
    </telerik:ClientTemplatesHolder>

    But, from within my MembersListView.cs I have tried just about everything to get a handle on these linkbuttons. Am i missing something obvious?

    protected override void  CreateChildControls() {
     
        base.CreateChildControls();
     
        this.oGrid.ItemDataBound += new Telerik.Web.UI.GridItemEventHandler(oGrid_ItemDataBound);
     
    }
     
     
    void oGrid_ItemDataBound(object sender, Telerik.Web.UI.GridItemEventArgs e) {
     
        LinkButton oEnableLinkButton = e.Item.FindControl("lnkbtnEnableUser") as LinkButton;
        if (oEnableLinkButton != null) {
     
            ((LinkButton)oEnableLinkButton).Command += new CommandEventHandler(MembersListView_Command);
            ((LinkButton)oEnableLinkButton).Text = "Hi";
     
        }
     
     
    }
     
    void MembersListView_Command(object sender, CommandEventArgs e) {
     
        Context.Response.Write(e.CommandName);
     
    }

    Thanks
    higgsy

  17. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    06 Jan 2011
    Link to this post
    Ivan,

    Don't worry - im being stupid. The data is bound on the client side using the webservice. I've used js.

    Al
Register for webinar
17 posts, 0 answered