Showing posts with label Silverlight. Show all posts
Showing posts with label Silverlight. Show all posts

Tuesday, 7 May 2013

Wiring events to a Popup control in Silverlight

Last week I was doing some work on a Silverlight application and I was struggling with an event not firing for a calendar control inside a popup control and it turns out that the reason is very simple, I was wiring the event to the popup rather than the calendar control inside the popup.

This is the method I used to create the calendar within the popup. 

private void CreateCalendar()
{
    if (calendar == null)
    {
        calendar = new Calendar();
        calendar.SetValue(Grid.ColumnProperty, 10);
        calendar.SetValue(Grid.RowProperty, 0);
        calendar.SetValue(Grid.RowSpanProperty, 7);
        calendar.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
      
        var StartDateBinding = new System.Windows.Data.Binding();
        StartDateBinding.Path = new PropertyPath("StartDate");
        StartDateBinding.Mode = System.Windows.Data.BindingMode.TwoWay;
        StartDateBinding.ValidatesOnDataErrors = true;
        calendar.SetBinding(Calendar.SelectedDateProperty, StartDateBinding);

        var displayDateBinding = new System.Windows.Data.Binding();
        displayDateBinding.Path = new PropertyPath("CalendarStartsOn");
        calendar.SetBinding(Calendar.DisplayDateStartProperty, displayDateBinding);

        popup.DataContext = viewModel;

        popup.Child = calendar;            

        calendar.MouseLeave += (o, e) =>
        {
            popup.IsOpen = false;
            LayoutRoot.Children.Remove(popup);
        };
  
 calendar.SelectedDatesChanged += (o, e) =>
        {
     CreateAppointment();
            popup.IsOpen = false;
            LayoutRoot.Children.Remove(popup);
        };

    }

}

The calendar and popup objects are global objects of the MainPage partial class (i.e. they can be found in main.xaml.cs) and the CreateCalendar method gets called on the constructor, via the AddPopUp method, see below

The popup is closed when a date is selected, in which case we create an appointment, method not shown, for the user or when the mouse leaves the calendar.

private void AddPopUp()
{    
    CreateCalendar();
    LayoutRoot.Children.Remove(popup);
    LayoutRoot.Children.Add(popup);
    
    popup.VerticalOffset = 50;
    popup.HorizontalOffset = Application.Current.Host.Content.ActualWidth - 100;
    
    popup.IsOpen = true;
}

Thursday, 2 May 2013

Set Regional Settings (culture) in Silverlight application.

Today I was looking at some issues with date formats, why in god's name do the american's use a different date system than everybody else?, and I ended up using the following code to set up the Regional Settings (No prizes for guessing where I work):

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
 
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
 
    var root = RootVisual as  MainPage;
    if (root != null)
    {
     root.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
    }
}

This is in the App.xaml code behind file.

Note that annoyingly, this will not work in WPF.


Tuesday, 7 February 2012

Debugging Silverlight Web Resources for MS Dynamics CRM 2011

I read this post about debugging Silverlight and it felt like too much of hack. So I thought I would present my far superior (I'm kidding here, I do think it's neater, though) solution.

Assuming that you have followed the tutorial on the SDK or on this page, you should have a file called SilverlightUtilty.cs and in this file you will have a method called GetSoapService. All you need to do is make use of the #if directive.

#if !DEBUG
            Uri serviceUrl = CombineUrl(GetServerBaseUrl(), "/XRMServices/2011/Organization.svc/web");
#else
            Uri serviceUrl = new Uri("http://localhost/testorg/XRMServices/2011/Organization.svc/web");
#endif

You also need to ensure that you only use the Debug build for your development environment and Release for production, but you are doing that already, right?. At any rate, here is a step by step guide:
  1. Set up Silverlight project following this tutorial.
  2. Change code in SilverlightUtility.cs as described above.
  3. Create clientaccesspolicy.xml file:

    <?xml version="1.0" encoding="utf-8"?>
    <access-policy>
     <cross-domain-access>
      <policy>
       <allow-from http-request-headers="*">
        <domain uri="*"/>
       </allow-from>
       <grant-to>
        <resource path="/" include-subpaths="true"/>
       </grant-to>
      </policy>
     </cross-domain-access>
    </access-policy>
    

  4. Copy clientaccesspolicy.xml to the website directory (normally c:\Program Files\Microsoft Dynamics CRM\CRMWeb\).
  5. Debug from Visual Studio.
  6. Ensure that you compile it as Release before you deploy it to other environments.
Note that if you use the same org name in Dev, Test and Prod, you could change the code to simply:
Uri serviceUrl = new Uri("http://localhost/org/XRMServices/2011/Organization.svc/web");

Saturday, 4 February 2012

WhoAmIRequest from a Silverlight Web Resource in MS Dynamics CRM 2011

Probably the simplest request that can be made in MS Dynamics CRM, is a WhoAmI request. This request returns details (UserId, BusinessUnitId & OrganizationId) of the current user or the user under whose context the code is running.

Note that this code, assumes that you have followed the "Use the SOAP Endpoint for Web Resources with Silverlight" walkthrough from the SDK, which can also can be found here.
private void WhoAmIButton_Click(object sender, RoutedEventArgs e)
{
    OrganizationRequest req = new OrganizationRequest() { RequestName = "WhoAmI" };
    IOrganizationService service = SilverlightUtility.GetSoapService();

    service.BeginExecute(req, new AsyncCallback(WhoAmIResult), service);
}
As per usual with Silverlight, it is necessary to make a callback to get the response, which is below:
private void WhoAmIResult(IAsyncResult result)
{
  try
  {
      OrganizationResponse response =  
              ((IOrganizationService)result.AsyncState).EndExecute(result);
 
      Guid userId = new Guid(response["UserId"].ToString());
  }
  catch (Exception ex)
  {                
      throw ex;
  }
}
Do note that if you need the UserId value to perform another query, you'll need to ensure that the second query is not made until this one (WhoAmIResult) has finished.

Friday, 3 February 2012

Making an Appointment Request from a Silverlight Web Resource in MS Dynamics CRM 2011

I’ve been looking at upgrading one of our Apps to MS Dynamics CRM 2011 and one of the things that we do a lot of is appointment booking.

At the moment, we have an iFrame showing an ASP.NET webpage with some buttons that when pressed, make an ajax call to a web method hosted in the ISV folder. Once the appointment is selected, the actual booking of the appointment is handled by a plug-in. I wanted to see whether we could remove the iFrame and use a Silverlight webresource.

I have to say that I found it a bit confusing and it took me quite a few attempts to get the RequestName right, this post by Jamie Miller sent me in the right direction. The search for appointments is started by a user clicking a button.

Note that this code, assumes that you have followed the "Use the SOAP Endpoint for Web Resources with Silverlight" walkthrough from the SDK, web link can be found here.

Here is the method that makes the appointment request:

private void checkButton_Click(object sender, RoutedEventArgs e)
{           
    AppointmentRequest appReq = new AppointmentRequest
    {
        Objectives = new ObservableCollection<ObjectiveRelation>(),
        RequiredResources = new ObservableCollection<RequiredResource>(),
        AppointmentsToIgnore = new ObservableCollection<AppointmentsToIgnore>(),
        Constraints = new ObservableCollection<ConstraintRelation>(),
        Sites = new ObservableCollection<Guid>(),
        Duration = 60,
        Direction = SearchDirection.Forward,
        NumberOfResults = 5,
        ServiceId = new Guid("DD535FD0-F84B-E111-8F2F-00505688095F"),
        SearchWindowStart = DateTime.UtcNow,
        SearchWindowEnd = DateTime.UtcNow.AddDays(7.0),
        AnchorOffset = 300
    };
   
    OrganizationRequest req = new OrganizationRequest() { RequestName = "Search" };
    
    req["AppointmentRequest"] = appReq;

    IOrganizationService service = SilverlightUtility.GetSoapService();

    service.BeginExecute(req, new AsyncCallback(GetAppReqResult), service);
}
As this is Silverlight, an asynchronous callback is needed to actually invoke the request, which is done by the method below.
private void GetAppReqResult(IAsyncResult res)
{
   try
   {
     OrganizationResponse resp = 
                          ((IOrganizationService)res.AsyncState).EndExecute(res);
   
     SearchResults results = (SearchResults)resp["SearchResults"];
   
     this.Dispatcher.BeginInvoke(() => ProcessAppointments(results));        
   
   }
   catch (Exception)
   {
       MessageBox.Show("Error Occurred");
   }
}

Not shown here is the ProcessAppointments method, which updates a DataGrid object in the Silverlight Web Resource.