Friday, June 29, 2012

Simple Extension Methods (part 2)

In the previous post I presented an extension method used mostly for overriding the edit and delete commands of a collection. One may ask “why do I want to do this?”. Apart from any other requirements/business logic dependent reason one might want to implement, for me there is one simple yet important reason: I don’t like at all (to be kind) the default add/edit modal windows when adding or editing an entry. It’s not a coincidence that the FIRST sample I wrote for LightSwitch and posted in the Samples of msdn.com/lightswitch was a set of extension methods and contracts to easily replace standard modal windows with custom ones.
Most of the times when I have an editable grid screen, selecting Add or Edit I DON’T want the modal window to pop-up, I just want to edit in the grid. Or in list and details screen I want to edit the new or existing entry in the detail part of the screen.
This is the main reason I most of the times override the default Add/Edit command behavior. And for this reason I created and use the next two extension methods:
public static void AddFocus<T>(this VisualCollection<T> collection, string focusControl, bool inCollection)
      where T : class, IEntityObject {
      collection.AddNew();
      collection.EditFocus(focusControl, inCollection);
    }

    public static void EditFocus<T>(this VisualCollection<T> collection, string focusControl, bool inCollection)
      where T : class, IEntityObject {
      if (focusControl != null) {
        try {
          IContentItemProxy control = null;
          if (inCollection)
            control = collection.Screen.FindControlInCollection(focusControl, collection.SelectedItem);
          else
            control = collection.Screen.FindControl(focusControl);
          Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() => {
            try {
              control.Focus();
            }
            catch {
              collection.EditSelected();
            }
          });
        }
        catch {
          if (collection.HasSelection())
            collection.EditSelected();
        }
      }
    }





So what you have to do in your MyCollectionAddAndEditNew_Execute partial method is write something like:
MyCollection.AddFocus("TheNameOfTheControlYouWantToFocus", true);



or for MyCollectionEdit_Execute partial method:
MyCollection.EditFocus("TheNameOfTheControlYouWantToFocus", true);

if you have a list detail screen the same code applies but with inCollection = false.

One could implement one method for collections and one for details. Also notice where constraints applied to T generic parameter. The class constraint is required for declaring VisualCollection<T>. The IEntityObject constraint is required so that we avoid the arbitrary casting of collection.SelectedItem to IEntityObject so as to be passed to FindControlInCollection as second parameter.

Notice that in the extension methods I don’t check if the control name exists. I just use try catch. On error (if the control name is not valid) I choose to fall-back to the default behavior. You can change this without any intellectual rights being violated Smile.

Tuesday, June 26, 2012

Simple Extension Methods (part 1)

As soon as I started writing LightSwitch applications I noticed that many times I was repeating the same code over and over for trivial tasks. So after all this time I have collected a number of extension methods that I widely use in my apps.
For me reusing code is a must and although the implementation of LS (IMHO) does not provide for this out of the box the underlying framework is ideal for writing extension classes and methods that are a major step towards code reusability. If you have downloaded any of my samples from msdn or have seen my Application Logo post, you already suspect I am an “extension method fanatic”.
So I will present a small series (I don’t know how small) of posts with extension methods from my Base.LightSwitch.Client library.
The first method is one of the first (if not the first one) extension methods I wrote. As soon as you want to override the code for default commands like Edit and Delete for a collection (let’s name it MyCollection) you have to write something like that:
partial  void MyCollectionDelete_CanExecute(ref bool result){
  if (this.MyCollection is null || this.MyCollection.SelectedItem == null)
    result = false;
  else
    result = true;
}

This is the minimum code (it can be written more elegantly I know but this is the concept) you need to write. I don’t take into account the permissions issue.

A similar chunk of code has to be written for Edit.

Isn’t the code listed below easier to read:
partial  void MyCollectionDelete_CanExecute(ref bool result){
  result = this.HasSelection("MyCollection");
}
It’s not only easier to read but is less error prone than the original. Plus you can inject any security logic in this HasSelection method.
And this is the code:
public static bool HasSelection(this IScreenObject screen, string collectionName) {
  if (!screen.Details.Properties.Contains(collectionName))
    return false;
  IVisualCollection collection =
    screen.Details.Properties[collectionName].Value as IVisualCollection;
  return collection != null &&
         collection.SelectedItem != null &&

         (collection.SelectedItem as IEntityObject).Details.EntityState != EntityState.Deleted;
}
For the ones that dislike using string property names I can suggest this version :
public static bool HasSelection<T>(this VisualCollection<T> collection) where T : class, IEntityObject {
  return collection != null &&
         collection.SelectedItem != nul &&
         collection.SelectedItem.Details.EntityState != EntityState.Deleted;
}


This version is more concrete is generic and also does not have to do the (out of thin air) conversion of SelectedItem to IEntityObject. If you use this version though you have to change your partial method as you cannot extend null:
partial void MyCollectionDelete_CanExecute(ref bool result){
  result = MyCollection!= null && MyCollection.HasSelection();
}
The choice is yours…Smile

Friday, June 22, 2012

RIAlity Issues

Recently I had to face a very frustrating issue regarding the integration of a RIA Service as a LightSwitch Datasource. I tried to find references for it in the web. I did. But none of them (at least the ones I managed to find) didn’t seem to match my case. So after solving my issue I thought sharing was a good idea…
After having implemented and tested my RIA service using a small Silverlight application I decided to add a datasource and use it. Which I did. Focusing at the part of the RIA service that caused the problem, I had a class called ImageAttachment and 2 queries exposing it. Below you can see the initial code:
   1:      [Query(IsDefault = true)]
   2:      public IQueryable<ImageAttachment> GetImageAttachments() {
   3:        return new List<ImageAttachment>().AsQueryable();
   4:      }
   5:   
   6:      public IQueryable<ImageAttachment> GetFolderItemImageAttachments(Guid? providerId, string folderId, string mailItemId) {
   7:        if (!providerId.HasValue || folderId == null || mailItemId == null)
   8:          return GetImageAttachments();
   9:        return GetAttachments(providerId.Value, folderId, mailItemId);
  10:      }



Importing the RIA Service GetFolderItemImageAttachments was properly imported as an optional query for ImageAttachment.

image

I added an ImageAttachment visual collection in a screen fetching results from GetFolderItemImageAttachments query. Everything worked smoothly. But when the time came to load the visual collection (i.e. run the query) I got an exception I hadn’t come across before neither as a LS developer nor as a Silverlight one:

Load operation failed for query ‘GetFolderItemImageAttachments’.  The remote server returned an error: NotFound.

The behavior was very strange. Although the query was recognized and imported from LS for some reason at runtime it looked like the method was not found. I placed a breakpoint at the method and it didn’t hit. The method was never called. Before doing this I was sure it was some bug of mine in the implementation that caused the RIA service to throw this generic exception. But no! The execution never reached the web method. It was then that I decided to “google” it. Looked like it was a RIA Services+LightSwitch(?) issue. All references where either not appropriate in my case or had no effect. Then I did what I usually do when I have problem I cannot solve: I scrolled to the part of code listed above and started to just stare at the code waiting for an answer. And I came to me! Why not make sure the query method IS a query? So what I did was just add the QueryAttribute to my method with no parameters:

   1:      [Query(IsDefault = true)]
   2:      public IQueryable<ImageAttachment> GetImageAttachments() {
   3:        return new List<ImageAttachment>().AsQueryable();
   4:      }
   5:   
   6:      [Query]
   7:      public IQueryable<ImageAttachment> GetFolderItemImageAttachments(Guid? providerId, string folderId, string mailItemId) {
   8:        if (!providerId.HasValue || folderId == null || mailItemId == null)
   9:          return GetImageAttachments();
  10:        return GetAttachments(providerId.Value, folderId, mailItemId);
  11:      }




I thought that if it didn’t solve the problem I surely would not cause a new one. It IS a query method after all. Why let LS infer it? And it worked.

I am quite sure I was lucky. I mean, the query was recognized either way. I cannot explain what exactly was the bug the QueryAttribute fixed. To stress my point more, I have to admit that went back to the RIA Service and I removed the attribute. Still worked! Like a deadlock resolved. Maybe only LightSwitch Team can explain. Anyhow I thought of sharing in case anyone else runs into something like this.Smile

Monday, June 11, 2012

You Are I.

Finding my application’s URI address either in deployment or development/debugging environment has been an issue I had to face in my early LightSwitch days. Although not a LightSwitch issue, but rather a Siverlight/ASP.NET one, I thought that sharing the 2 lines of code I have ended up using to discover the URI (along with the port, most important for debugging and/or standalone deployments) might be useful.
First the client. The first and easy approach was extracting the URI and port from System.Windows.Browser.HtmlPage.Document.DocumentUri. Nice! Not really. This only works for web and NOT OOB (Out of Browser) or Desktop according to LS naming, applications. System.Windows.Browser namespace is in general not available in ΟΟΒ applications.
The way I ended up adopting is accessing System.Windows.Application.Current.Host.Source.AbsoluteUri. Ok, I know it’s WPF/Silverlight way (System.Windows… I mean) but my experience says that a similar approach will be available even if HTML 5 is the next (not too soon I expect) output of LS.
Then the server. Here things are simpler and for as long as the server part of a LS application remains a Web Service the path will always be the same: HttpContext.Current.Request.Headers["HOST"].
That’s it! Short but juicy (I hope Smile).

Monday, June 4, 2012

CLASS Extensions Version 2 Fixes and Promises

Although it's been some time since my last post, I didn't quit on CLASS Extensions. On the contrary, I have been very busy working for a corporate project that uses CLASS Extensions and in the process I have made additions and fixes in CLASS Extensions. The most important fix is about Drawing business type and control so as to support standalone deployment.
As you might know, when running standalone a new host is launched every time, listening to a different port. As the drawing business type uses uris to set the drawing's background, the port active when the image was selected from the server, is included in the drawing serialization string. This means that next time the application is launched (standalone or debugging) and the port is changed the drawing's background is lost. This is fixed. Although the port is still serialized along with the drawing the port is automatically replaced with the current port of the hosting process.
There are also other small fixes regarding functionality.
Additions are to be announced officially but a (not all inclusive) sample list would include:

  • an expander group control allowing you to expand/collapse regions of your screen (both horizontal and vertical).
  • an ImageContainer group control that adds standard functionality to image editors and drawing controls to import automatically from camera and scanner (yes Del Sole's code is at the background, so before publishing I will definetly ask for permissions)
  • a printable area group control which allows to both save a snapshot of the contained screen region and/or print it.
  • a new color picker control that allows you to define a color by selecting it directly from an image using a sampler tool.
The additional features will not be released before the end of August. The price will be adjusted accordingly. Anyone that has already purchased the original version until then, they will get the new features for free earlier than official release for beta testing.

Friday, March 23, 2012

CLASS Extensions Version 2 Released

CLASS Extensions version 2 is now available. All the features demonstrated in the demo videos are included plus the AttachmentsListEx collection control that is demostrated in the sample application but was not mentioned in the previous post.

Features




  • Color Business type and Controls. This business type is used to represent color values. The underlying CLR type is integer. After a request the change from the previous free version is that by default the pop-up window color picker control is used both for details and collections. Boolean property called “Drop Down” was added in the Appearance category which is false by default. When checked the drop-down/expander color picker control is used instead. This property is ignored in collections (grids/lists etc.) and pop-up is used. The color-picker control (as mentioned in the first version also) is contained in SilverlightContrib Codeplex project under Ms-PL.
    image
  • Boolean Checkbox & Boolean Viewer controls. These controls handle bool and bool? (Nullable<bool>) values. No changes made from the previous – free – version.
    checkedchecked_dimmeduncheckeduncheckeddimmedundefinedcheckundefinedcheck_dimmed
  • Rating Business type and Controls. This business type is used to represent rating values. The underlying CLR type is integer. The control is using the Mark Heath’s Silverlight Star Rating Control from CodePlex under Ms-PL.
    image
  • Percentage Business type and Controls. This business type is used to represent percentages. The underlying CLR type is decimal. In read-only mode a progress bar is displayed which is green for percentages <= 100% and red otherwise. It’s ideal for representing progress.
    imageimage
  • ImageURI Business type and Controls. This business type is used to display an image from a URI location. The underlying CLR type is string. You can define a thumbnail view and size and also choose if the URI should be visible (editable if not read-only). Stretch Image property applies Uniform stretch to the image.
    image
  • AudioFile Business type and Controls.This business type is used to store and reproduce audio files from a URI location. The underlying CLR type is string. You can choose if the URI should be visible (editable if not read-only). Play, Pause, Stop, Volume Control are available. Progress is also displayed.
    image 
  • VideoFile Business type and Controls. This business type is used to store and reproduce video files from a URI location. The underlying CLR type is string. You can choose if the URI should be visible (editable if not read-only). Play, Pause, Stop, Volume Control are available. Progress is also displayed.
    image
  • DrawingFile type and Control. This business type is used to store drawings. The underlying CLR type is string. The background of the drawing is defined as an image URI (not binary). Using the control you can draw lines, polygons and texts on a layer over the image store and edit afterwards to delete drawings, move edit or delete texts, change fonts and colors e.t.c. The control can also operate in local mode, where all drawings are saved in application’s Isolated Storage. Every time a drawing is saved a png image snapshot of the drawing is also generated and can be easily (with 2 lines of code) saved in traditional Image (byte[]) fields.
    imageimage
  • AttachmentsListEx Collection Control. This is a special use collection control used to represent collections of entities implementing CLASSExtensions.Contracts.IAttachment.
    image
  • FileServer Datasource Extension. A very important RIA Service datasource provided to smoothly integrate all the URI-based features. This Datasource exports two entity types: ServerFile and ServerFileType. Also provides methods to retrieve ServerFile entities representing the content files (Image, Audio, Video, Document, In the current version these are the ServerFileTypes supported) stored at your application server. Also you can delete ServerFile entities. Upload (insert/update) is not implemented in this version as depending on Whether your application is running out of browser or not it has to be done a different way. Maybe in an update. The idea for this datasource was based on this article of Michael Washington.
  • A good numbered (30+) collection of ValueConverters and Extension Classes. You can reuse in your applications either to create your own custom controls and extensions or application code in general.


  • Pricing

    The price is 50$ for the package without the code. Depending on demand a code inclusive version and pricing may become available. The payment is done through PayPal and if invoice is required will be sent by post. After payment you will receive a zip file containing the vsix file the sample application used for the demostration videos.

    Remarks

    • Regarding Rating business type the Maximum and Default rating properties have to be set on the control. Although I found I way to add attributes to the business type, I couldn’t find a way to retrieve in the control so that these parameters could be set once on the entity’s property.
    • The reason DrawingFile is using URI as image background and not a binary image was a result of my intention to create a lightweight drawing type which is also portable. As long as the image URI is public the drawings can be ported to any other application using the extension copying just a few KBs.
    • For the FileServer Datasource to work you must create a folder hierarchy in your web application’s folder. You have to create a Content (see also ContentDirectory appSetting below) sub-folder in the root folder of your application and a hierarchy like shown below. If the folders are not there, an attempt will be made by code to be created, but to avoid extra permissions issues you can create in advance. Also if you want to be able to delete files you have to take care of file permissions so that the account can delete files.
      image
      Also, as you can see in the sample application you will receive along with the extensions, in ServerGenerated\web.config there are 2 appSettings entries:

      <add key="VirtualDirectory" value="" />
      <add key="ContentDirectory" value="Content" />

      The first one VirtualDirectory is compulsory and if your application is not running at the root of the publishing site the value should be the name of the virtual directory under which your application is running. In the sample the value is null.
      The second one ContentDirectory is optional and if omitted then Content is assumed as the folder to look for files.
    • For AudioFile and VideoFile controls: The total duration of the media file is not always available so many times in the rightmost digital time display the value will be zero.
    • For all URI based types: If you are using the FileServer Datasource while debugging you will have issues regarding the validity of the URIs. As between builds and runs the host’s port can change, a URI provided from the FileServer Datasource (containing the current port) during one debug session, may be invalid in a next session if the port changes. Of course after deployment this will never be an issue unless you somehow change your application’s URL.

    Saturday, March 17, 2012

    CLASS Extensions Version 2 Demo

    After a long time of preparation, my company Computer Life and me we are ready to publish the next –commercial- version of CLASS Extensions.

    In this SkyDrive location you can find 2 videos briefly presenting capabilities of this new version. In less than a week a page will be started here, where you would be able to buy the package you prefer. There will be 2 packages: no source code and with code and code documentation. Pricing will be announced along with the official release.

    CLASS Extensions Demo Part I.swf

    Part1

    CLASS Extensions Demo Part II.swf

    Part2

    In these videos you will find a brief demonstration of the following controls and/or business types:

    • Color Business Type and Control. This was available also in the first free version. It has been improved to automatically detect grid or detail and read-only or not.
    • BooleanCheckbox and BooleanViewer controls. These were also available in the first version. No change to this one.
    • Rating Business Type and Control. A new business type to support ratings. You can set maximum rating, star size, show/hide starts and/or labels, allow/disallow half stars.
    • Image Uri Business Type and Control. A new business type to support displaying images from a URI location instead of binary data.
    • Audio Uri Business Type and Control. A new business type to support playing audio files from a URI location.
    • Video Uri Business Type and Control. A new business type to support playing video files from a URI location.
    • Drawing Business Type and Control.  A new business type that allows the user to create drawings using an image URI (not binary) as background. The drawing can be saved either as a property of an entity (the underlying type is string) or in the IsolatedStorage of the application. Also, every time the drawing is saved a PNG snapshot of the drawing is available and can be used any way you want, with 2 (two) lines of additional code. The drawings, both local or data service provided, can be retrieved any time and modified and saved back again.
    • FileServer Datasource Extension. A very important RIA Service datasource provided to smoothly integrate all the URI-based features. This Datasources exports two EntityTypes: ServerFile and ServerFileType. Also provides methods to retrieve ServerFile entities representing the content files (Image, Audio, Video, Document, In the current version these are the ServerFileTypes supported) stored at your application server. Also you can delete ServerFile entities. Upload (insert/update) is not implemented in this version as depending on Whether your application is running out of browser or not it has to be done a different way.

    Last but not least. There is a list of people whose code and ideas helped me a lot in the implementation of this version. Upon official release they will be properly mentioned as community is priceless.