Filter appointments by sending additional information to the Web Service and the provider

12 posts, 0 answers
  1. Telerik Admin
    Telerik Admin avatar
    1679 posts
    Member since:
    Oct 2004

    Posted 23 Nov 2011 Link to this post

    Requirements

    RadControls version

     Q1 2011 or later

    .NET version

     4.0

    Visual Studio version

     2010

    programming language

     C# and VB.NET

    browser support

    all browsers supported by RadControls


    PROJECT DESCRIPTION

    The attached samples show how to filter appointments by sending additional information to the Web Service and the provider. Here are the help topics that describe the approach in a step-by-step fashion: SchedulerDbProvider.zip contains a demo with a custom Data Base Scheduler provider. You can add this scenario to your application using Telerik Visual Studio Extensions - http://screencast.com/t/6mBhGX6KYoa

    SchedulerCustomXmlProvider.zip contains a stand-alone sample of the Web Service Binding online demo.

    Here is a step-by-step tutorial on how the SchedulerCustomXmlProvider is implemented:

    1. Create a custom class that inherits from SchedulerInfo and expose a property that will carry the filter criteria. In this case we will need an array of strings to take on the names of the selected resources. 

      App_Code/MySchedulerInfo.cs:
      public class MySchedulerInfo : SchedulerInfo
      {
          public string[] CategoryNames { get; set; }
          public MySchedulerInfo(ISchedulerInfo baseInfo, string[] categoryNames)
              : base(baseInfo)
          {
              CategoryNames = categoryNames;
          }
          public MySchedulerInfo()
          {
       
          }
      }

       
    2. In SchedulerWebService.cs, change the parameter type for all the methods from SchedulerInfo to MySchedulerInfo. Also specify the provider - CustomXmlSchedulerProvider, which we will create in step 5.
      public class SchedulerWebService : WebService, IRequiresSessionState
      {
          private WebServiceAppointmentController _controller;
          public const string ProviderSessionKey = "SchedulerWebServiceData";
       
          private WebServiceAppointmentController Controller
          {
              get
              {
                  CustomXmlSchedulerProvider provider;
                  if ((Session[ProviderSessionKey] == null))
                  {
                      provider = new CustomXmlSchedulerProvider(Server.MapPath("~/App_Data/Appointments_Outlook.xml"), false);
                      Session[ProviderSessionKey] = provider;
                  }
                  else
                  {
                      provider = (CustomXmlSchedulerProvider)Session[ProviderSessionKey];
                  }
       
                  if (_controller == null)
                  {
                      _controller = new WebServiceAppointmentController(provider);
                  }
       
                  return _controller;
              }
          }
           
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> GetAppointments(MySchedulerInfo schedulerInfo)
          {
              return Controller.GetAppointments(schedulerInfo);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> InsertAppointment(MySchedulerInfo schedulerInfo, AppointmentData appointmentData)
          {
              return Controller.InsertAppointment(schedulerInfo, appointmentData);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> UpdateAppointment(MySchedulerInfo schedulerInfo, AppointmentData appointmentData)
          {
              return Controller.UpdateAppointment(schedulerInfo, appointmentData);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> CreateRecurrenceException(MySchedulerInfo schedulerInfo, AppointmentData recurrenceExceptionData)
          {
              return Controller.CreateRecurrenceException(schedulerInfo, recurrenceExceptionData);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> RemoveRecurrenceExceptions(MySchedulerInfo schedulerInfo, AppointmentData masterAppointmentData)
          {
              return Controller.RemoveRecurrenceExceptions(schedulerInfo, masterAppointmentData);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<AppointmentData> DeleteAppointment(MySchedulerInfo schedulerInfo, AppointmentData appointmentData, bool deleteSeries)
          {
              return Controller.DeleteAppointment(schedulerInfo, appointmentData, deleteSeries);
          }
       
          [WebMethod(EnableSession = true)]
          public IEnumerable<ResourceData> GetResources(MySchedulerInfo schedulerInfo)
          {
              return Controller.GetResources(schedulerInfo);
          }
      }
    3. In RadSchedulerWebForm.aspx, handle onchange of the checkboxes to rebind RadScheduler. Also, extract the names of the selected checkboxes and store them in an array using jQuery.
      <script type="text/javascript">
      var categoryNames = new Array();
       
      function addSelectedCategoriesToArray(categoryNamesArray) {
                  var $ = $telerik.$;
                  var categoryPanelBar = $find('<%=RadPanelBar1.ClientID %>');
                  $(':checkbox:checked', categoryPanelBar.get_element()).each(function () {
                      categoryNames.push($(this).attr('name'));
                  });
              }
       
       
      function rebindScheduler() {
                  var scheduler = $find('<%=RadScheduler1.ClientID %>');
                  scheduler.rebind();
              }
      ***
      </script>
       
      <input id="chkDevelopment" type="checkbox" title="Development" onchange="rebindScheduler()"
                                                      value="Development" checked="checked" name="Development" />
                                                  <span>Development</span>
    4. Populate the MySchedulerInfo property by handling OnClientAppointmentsPopulating:
      function OnClientAppointmentsPopulating(sender, eventArgs) {
                  addSelectedCategoriesToArray(categoryNames);
                  eventArgs.get_schedulerInfo().CategoryNames = categoryNames;
                  categoryNames = new Array(); //clear the array
              }
    5. Create a custom provider that inherits from XmlSchedulerProvider.

      App_Code/ CustomXmlSchedulerProvider.cs:
      public class CustomXmlSchedulerProvider : XmlSchedulerProvider
      {
          public CustomXmlSchedulerProvider(string dataFileName, bool persistChanges)
              : base(dataFileName, persistChanges)
          {
       
          }
      }

      Creating a custom provider might sound like a laborious task, but in this case it is quite simple and easy. We only need to override the GetAppointments method and let the XmlSchedulerProvider base do the rest of the work such as Inserting, Updating or Deleting appointments.
    6. Override the GetAppointments method and access the value of the CategoryNames property by casting the schedulerInfo parameter to MySchedulerInfo:
      public override IEnumerable<Appointment> GetAppointments(ISchedulerInfo schedulerInfo)
         {
             var myInfo = schedulerInfo as MySchedulerInfo;
             if (myInfo.CategoryNames != null)
             {
                 var appointmentsList = base.GetAppointments(schedulerInfo);
                 var appointmentsWithCalendarResource = appointmentsList.Where(a => a.Resources.GetResourceByType("Calendar") != null).Select(a => a);
       
                 var predicate = PredicateBuilder.False<Appointment>();
       
                 foreach (string categoryName in myInfo.CategoryNames)
                 {
                     string temp = categoryName;
                     predicate = predicate.Or(a => a.Resources.GetResourceByType("Calendar").Text == temp);
                 }
       
                 return appointmentsWithCalendarResource.AsQueryable().Where(predicate).Select(a => a).AsEnumerable();
             }
             else
             {
                 return base.GetAppointments(schedulerInfo);
             }
         }
    7. Once you get a hold of the selected category names (myInfo.CategoryNames) there are various ways to filter the appointments list (base.GetAppointments(schedulerInfo)).  Using LINQlambda expressions and a predicate builder for example is a neat way to do this. You will need to add the System.Linq.Expressions namespace and a PredicateBuilder class:
      public static class PredicateBuilder
      {
          public static Expression<Func<T, bool>> True<T>() { return f => true; }
          public static Expression<Func<T, bool>> False<T>() { return f => false; }
       
          public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                              Expression<Func<T, bool>> expr2)
          {
              var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
              return Expression.Lambda<Func<T, bool>>
                    (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
          }
       
          public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                               Expression<Func<T, bool>> expr2)
          {
              var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
              return Expression.Lambda<Func<T, bool>>
                    (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
          }
      }

      Note that when using a predicate builder, it is important to create a temp string variable because categoryName is of type string which is a reference type. Otherwise, the predicate builder will use just the last value for catergoryName in the foreach cycle .
      foreach (string categoryName in myInfo.CategoryNames)
      {
          string temp = categoryName;
          predicate = predicate.Or(a => a.Resources.GetResourceByType("Calendar").Text == temp);
      }

       
  2. Alok
    Alok avatar
    4 posts
    Member since:
    Jan 2012

    Posted 04 Jan 2012 Link to this post

    Hi

         I have went through http://demos.telerik.com/aspnet-ajax/scheduler/examples/resourceavailability/defaultcs.aspx ,in which all available  room displayed ,i have same situation in which i need to display all my resources and his available time.how can i do the same thing MVC 3 project. can i get a sample application using .net 4.0 and MVC 3.

     

    Thanks

    Alok Gupta

  3. anuj
    anuj avatar
    11 posts
    Member since:
    Oct 2012

    Posted 17 Oct 2012 Link to this post

    I am using the same demo with calender.  when i am making GroupBy="Teacher" .And when i am clicking in calender date resource header is getting added.
    Thanks
  4. Plamen
    Admin
    Plamen avatar
    2733 posts

    Posted 19 Oct 2012 Link to this post

    Hello Anuj,

    I could not observe the described behavior. Would you please elaborate what should be done in order to reproduce this issue locally because it is not very clear?

    Greetings,
    Plamen
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now
  5. anuj
    anuj avatar
    11 posts
    Member since:
    Oct 2012

    Posted 19 Oct 2012 Link to this post

    Hello Plamen
    Thanks for your reply.

    I am making scheduler based on this demo using web services :
    http://demos.telerik.com/aspnet-ajax/scheduler/examples/overview/defaultcs.aspx

    When i am making scheduler GroupBy="Teacher"  and i am filletring scheduler based on calender selected date.
    when page load its work fine. but whenever i am clicking on calender date resource header is getting add.
    suppose i fillter appointment 3 times clicking on calender resources header is getting added every time.
    That is the  problem.
  6. Plamen
    Admin
    Plamen avatar
    2733 posts

    Posted 24 Oct 2012 Link to this post

    Hi Anuj,

    I have inspected the described issue in the linked demo but could not observe any unusual behavior once again. First of all it is not clear by which exactly resource are you grouping since pointed RadScheduler has only one resource -Calendar. 

    I tried Grouping by Calendar by could not observe anything unusual. here is a video of my test. Please let me know if i am not testing properly or come other code should be added so I could reproduce the same behavior.

     

    All the best,
    Plamen
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  7. anuj
    anuj avatar
    11 posts
    Member since:
    Oct 2012

    Posted 29 Oct 2012 Link to this post

    Hello Plamen
    Thanks for your reply.
    Problem is that whenever i am filtering appointment based on calender selected date resource header is getting added.
    Below is demo which i have tested.
  8. Plamen
    Admin
    Plamen avatar
    2733 posts

    Posted 31 Oct 2012 Link to this post

    Hello Anuj,

     
    Thank you for explaining the issue deeper- this is the default behavior of RadScheduler. If you want to hide the resource headers(the ones with Mr John Doe and Mr Jane Smith) you cause the following css style:

    .RadScheduler .rsHorizontalHeaderTable th div {
          display:none !important;
            }

    Hope this will be helpful.

    Regards,
    Plamen
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  9. anuj
    anuj avatar
    11 posts
    Member since:
    Oct 2012

    Posted 02 Nov 2012 Link to this post

    Hello Plamen

    Thanks for your reply.
    Actually i need to show the resource header. so is there any way to show the resource header.

    Thanks
    Anuj

  10. Plamen
    Admin
    Plamen avatar
    2733 posts

    Posted 07 Nov 2012 Link to this post

    Hi Anuj,

    The default behavior of RadScheduler is to have the resource header shown when it is grouped by resources so it still net clear what is the desired behavior and what is the difference with the current one.

    All the best,
    Plamen
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  11. Prava kafle
    Prava kafle avatar
    212 posts
    Member since:
    Apr 2010

    Posted 14 Mar 2014 Link to this post

    Hi,

    I am trying to use webservice bound scheduler and grouping resources vertically (Group By Teachers).
    I am modified the sample code(SchedulerDbProvider.zip)  provided in this link to display appointments by teachers name, On doing so scheduler doesnot display any appointments and teachers. I just modified  HTML Tags and left webservice code as is.Am I missing anything?

    <telerik:RadComboBox ID="RadComboBox1" runat="server" OnClientSelectedIndexChanged="OnClientSelectedIndexChanged">
                <Items>
                    <telerik:RadComboBoxItem Text="All" Value="all" />
                    <telerik:RadComboBoxItem Text="Teacher 1" Value="1" />
                    <telerik:RadComboBoxItem Text="Teacher 2" Value="2" />
                </Items>
            </telerik:RadComboBox>
        </p>
        <telerik:RadScheduler ID="RadScheduler1" runat="server" OnClientAppointmentsPopulating="OnClientAppointmentsPopulating"
            AppointmentStyleMode="Default" SelectedView="WeekView" SelectedDate="2011-01-21"
            Width="600px"  
         
            >
           <WeekView UserSelectable="True" GroupBy="Teachers" GroupingDirection="Vertical"  />
            <WebServiceSettings Path="SchedulerWebService.asmx" ResourcePopulationMode="ServerSide" />
            <ResourceStyles>
                <telerik:ResourceStyleMapping Type="Teacher" Key="1" BackColor="Orange" />
                <telerik:ResourceStyleMapping Type="Teacher" Key="2" BackColor="Aqua" />
            </ResourceStyles>
        </telerik:RadScheduler>
    Thanks,
    Prava
  12. Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 19 Mar 2014 Link to this post

    Hello,

    As I noticed from the markup code the resource type is "Teacher. 
    <ResourceStyles>
                <telerik:ResourceStyleMapping Type="Teacher" Key="1" BackColor="Orange" />
                <telerik:ResourceStyleMapping Type="Teacher" Key="2" BackColor="Aqua" />
            </ResourceStyles>

    In the RadScheduler WeekView section you are grouping by "Teachers" instead of "Teacher" and most probably this causes the problem you are facing.  Please try to group by "Teacher" as shown in the code snippet:
    //markup code
    <WeekView UserSelectable="True" GroupBy="Teacher" GroupingDirection="Vertical"  />


    Regards,
    Boyan Dimitrov
    Telerik
     

    DevCraft Q1'14 is here! Watch the online conference to see how this release solves your top-5 .NET challenges. Watch on demand now.

     
Back to Top