LavaBlast Software Blog

Help your franchise business get to the next level.
AddThis Feed Button

CheckBoxList hover extender

clock January 22, 2008 09:16 by author JKealey

Summary

This article presents a CheckBoxList extender that enables the user to hover over individual checkboxes in the list and see a popup with additional information.  The information is populated dynamically (web service call) depending on the hovered checkbox' value.

[VIEW THE ONLINE DEMO]

[DOWNLOAD THE CODE] (469.00 kb)

Where could this be useful?

If you use the ManyToManyList in SubSonic, you know that it inherits from the built-in CheckBoxList control to display data from a many-to-many database relationship.  You probably also know that this can be really useful, but it has it's limitations.  We are using the SubSonic many-to-many list to display a list of stores that a user can be associated with.  You can display only one field of information by item with the ManyToManyList control for the foreign table associated in the relationship (unless you use views!).  Here is an example:

storesList

For a particular user, we are listing all possible stores and showing the store ID as a description for the items.  This can have a meaning for some users, but when a new user comes in and doesn't know the store identifiers, you have a problem. All franchise stores share the same store name as they do business under the same name - they can be uniquely identified by their franchisor-assigned ID or by their address. However, we don't want to show too much information in this control, as it would clutter the interface, in our system. We need a way to display more information by item, without taking up too much screen real estate.  

Our solution is very much inspired by the AjaxControlToolkit controls, such as the HoverMenu to display information when the user hovers over an item in our CheckBoxList (or SubSonic ManyToManyList).  We created an AJAX Control Toolkit Extender that asynchronously calls a web service method (or a page method) to obtain the information displayed in the popup control, when the user hovers over an item.  Here is an example of the result:

checkboxListhover

How to use it

You need a CheckBoxList, a panel to display the information, our extender, and a web service method to invoke.

<asp:CheckBoxList ID="CheckBoxList" runat="server">
    <asp:ListItem Text="Item #1" Value="1" />
    <asp:ListItem Text="Item #2" Value="2" />
    <asp:ListItem Text="Item #3" Value="3" />
    <asp:ListItem Text="Item #4" Value="4" />
    <asp:ListItem Text="Item #5" Value="5" />
</asp:CheckBoxList>

<asp:Panel ID="panelInfo" runat="server" CssClass="checkboxlisthover">
    <asp:Label ID="lblTest" runat="server" Text="Label"></asp:Label>
</asp:Panel>

<ajax:CheckboxListHoverExtender
id="checkboxlistext" runat="server"
TargetControlID="CheckBoxList"
PanelID="panelInfo"
DynamicServiceMethod="GetContent"
DynamicControlID="lblTest"
DynamicServicePath="~/CheckBoxList.asmx" />

The web service class should look something like this:

[ScriptService]
    public class CheckboxList : WebService
    {
        [WebMethod]
        [ScriptMethod]
        public string GetContent(string contextKey) { return "";}

    }

Implementation

A web service method was called with the value of the hovered checkbox.  When you DataBind the CheckBoxList, it is very important to assign a value to each of your ListItems.  In this example, each checkbox has a GUID value.  This GUID is passed as a parameter to the web service call automatically by the extender.  The popup panel is then filled with the information returned by the web service.

As stated previously, the CheckBoxListExtender control is very much inspired by the HoverMenu extender.  The two controls have similarities, but we can't use the HoverMenu directly in the CheckBoxList because we don't have access to the item template of a CheckBoxList.  This prevents us from using the built-in HoverMenu extender for each CheckBoxList item.

Coding a new extender

To code a new extender, you can use existing extenders to simplify your life: that's what we did for the CheckBoxListExtender.  It re-uses the HoverExtender and the PopupExtender.  Those two extenders are not in the sample page of the AjaxControlToolkit (we see the HoverMenuExtender and PopupControlExtender but not the two we are using here), but they are in the source code if you want to see them.  Basically when we coded the CheckBoxListExtender, we had to pass the scripts we wanted to depend on:

[RequiredScript(typeof(CommonToolkitScripts))]
[RequiredScript(typeof(HoverExtender))]
[RequiredScript(typeof(PopupExtender))]
[RequiredScript(typeof(AnimationExtender))]

[Designer(typeof(CheckboxListHoverDesigner))]
[ClientScriptResource("LavaBlast.AJAX.CheckboxListExtender.CheckboxListHoverBehavior", "LavaBlast.AJAX.CheckboxListExtender.CheckboxListHoverBehavior.js")]
[TargetControlType(typeof(CheckBoxList))]
public class CheckboxListHoverExtender : DynamicPopulateExtenderControlBase

As you can see, the extender inherits from DynamicPopulateExtenderControlBase.  This means that the extender can dynamically populate the control via a web service call and all the necessary plumbing is already in place. Specifying the scripts you depend on is as easy as using the RequiredScript attribute on your extender class.

JavaScript behavior

As for the JavaScript, for each "TD" inside our CheckBoxList control, we created a HoverBehavior (this is from the HoverExtender).  Each time the HoverBehavior events are fired, we can do something about them.  In this case, we simply activated the PopupBehavior to show the popup panel and call the web service method to populate the content.  As the value of each checkbox of the list is not contained in the DOM of the page, most probably a security feature of ASP.NET, you have to somehow pass this information from the server to the extender behavior.  Since we couldn't find a way to pass a list of values from the server to the behaviour using a generic List variable, we simply used a string of comma separated values.  Right now we're using this:

[ExtenderControlProperty]
[DefaultValue("")]
[Browsable(false)]
public string Values
{
    get { return GetPropertyValue("Values", ""); }
    set { SetPropertyValue("Values", value); }
}

But would much rather like to use the following: 

[ExtenderControlProperty]
[DefaultValue("")]
[Browsable(false)]
public List<string> Values
{
    get { return GetPropertyValue("Values", ""); }
    set { SetPropertyValue("Values", value); }
}

It appears generic lists are not supported, unless we are mistaken. If someone knows if this is possible, please leave us a comment on this post.

Don't forget to look at the online demo!

CheckBoxListHoverExtenderDemo.zip (469.00 kb)

kick it on DotNetKicks.com


Dirt Simple ASP.NET CMS using the ScrewTurn Wiki

clock January 22, 2008 00:08 by author JKealey

A year ago we wanted to quickly integrate the capabilities of a content management system in a customer’s website. Budget was limited but so were the requirements.

  • The user SHALL be able to change a few (a dozen) paragraphs on the website. 
  • The user SHALL be able to use basic formatting (bulleted lists, headers, images) without knowing HTML.

The lengthy option was the integration of a powerful CMS and the shorter one was to create something quickly using one of the many open source rich text editors found on the Internet and a simple database table. We didn’t really feel like coding that infrastructure at that point for various reasons. 

At this point, we were already a wiki for requirements management and task planning for this customer.  On very complex projects, we prefer TWiki because we had already used its metadata and form capabilities to make it easy to collaboratively work on software requirements back in 2005. However, we had installed the ScrewTurn wiki (an open source wiki in ASP.NET) for this customer, as its installation only takes a few seconds. We decided we would dynamically integrate content from our Wiki into our website, which was sufficient for our customer, for the time being.

We took a shorter lunch break that day and coded a dirt simple CMS application that queries the ScrewTurn wiki to obtain paragraphs of text. We simply made an HttpWebRequest to the printable version of the wiki page, cleaned out a bit of HTML markup that we did not need and cached the result. Using the control is then straightforward.

Register ScrewturnVisualizer in our Web.config (system.web, pages, controls):

<add tagPrefix="LB" assembly="LavaBlast" namespace=" LavaBlast.CustomControls" />

Add the base information in our Skin to avoid repeating it everywhere:

<LB:ScrewturnVisualizer runat="server" BaseURL="http://ourclientwiki.lavablast.com" CssClass="ScrewTurn" />

Add the control on the appropriate pages:

<LB:ScrewturnVisualizer ID="stv1" runat="Server" PageName="CurrentSpecials" />

Today, we’ve moved on to a full-fledged CMS and no longer use this code, but the attached code may still help someone out! We’re big fans of incremental engineering and this half hour of coding helped keep our clients happy while we moved to a better solution.

Side note: In terms of open source licences, I’ve always wondered what this would imply. ScrewTurn is GPL (as opposed to LGPL) and I’m curious to know if this would imply that websites using it as a simple CMS would have to be GPL as well. Because we’re making us of an online service (the code can quickly be adapted to work for any Wiki or other website) and not extending the codebase, I think we’re not bound by the GPL. Any thoughts?

ScrewturnVisualizer.zip (1.41 kb)

kick it on DotNetKicks.com


VS.NET 2008 IDE Frozen After Compilation

clock January 16, 2008 21:08 by author JKealey

Each and every time I've compiled my solution over the last month, I've had to wait approximately 30 seconds for the IDE to resume after compiling. It simply said Build failed / Build succeeded and would not let me click anywhere in the UI for a painful half-minute (which I put to good use).

At first, I assumed this was another "feature" of VS.NET that was causing me pain and suffering, just like when my VS.NET 2005 decided to make me pay for cheating on it with another IDE (Eclipse) when I was working on a few open source Java projects using Eclipse (StatSVN and jUCMNav).

Evil VS.NET 2005

I decided to launch VS.NET 2008 in Safe Mode to verify if this would fix my problem and, to my surprise, it did. I probably have an evil add-in that was migrated from VS.NET 2005... to be investigated.

Update: Even in safe mode, it started doing it again after a couple hours of work. I'll file this into the "unexplained" category, alongside my mysterious "clipboard doesn't work for large images when memory usage is too high". From what I can see, Windows 32bit with the /PAE or /3GB options simply doesn't work. I need to upgrade to a 64bit OS to use my 4GB ram because the startup options aren't working well for me.



Using { and } in string.Format

clock January 16, 2008 14:02 by author EtienneT

Have you ever tried to use the { and } characters in the c# string.Format() method?  If you have, then you probably ran into a problem.  I'm posting this because this little Gotcha might not turn up until much later if your string formats are dynamically loaded from some external source, such as RESX files.

In any case, I sometimes find it useful to write some JavaScript code directly in C# and then dynamically insert it into the page with the ScriptManager.  Here is a quick example:



Basically, I write my JavaScript code on multiple lines with the @"" notation.  Then, I have to escape all { and } characters using {{ or }} otherwise string.Format will run into a System.FormatException: Input string was not in a correct format exception.  I can customize my JavaScript (or insert control.ClientID parameters) this way while retaining a readable format in the C# code.



Attach to Process with one shortcut

clock January 11, 2008 11:40 by author EtienneT

In case you didn't know, there is a much faster way to debug an ASP.NET application when running IIS than hitting F5. You can directly attach the debugger to the existing w3wp.exe to quickly start your debug session by doing Debug -> Attach to Process -> w3wp.exe. After a while, you start using the "Attach to Process" command very often in a usual day.  I created a simple visual studio macro to automatically attach to the ASP.NET process when you need to debug a site.  Then you can call the macro with a simple keyboard shortcut.  Here is the code:

Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.Security.Principal

Public Module RecordingModule
    Sub AttachToAspNET()
        Try
            Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
            Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
            Dim compName As String = WindowsIdentity.GetCurrent().Name
            compName = compName.Substring(0, compName.IndexOf("\"))
            Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, compName).Item("w3wp.exe")
            proc2.Attach2(dbgeng)
        Catch ex As System.Exception
            MsgBox(ex.Message)
        End Try
    End Sub
End Module


To create the macro in your Visual Studio, just open the Macro Explorer in Tools->Macro->Macro Explorer, make a new macro and copy paste the code. The only thing you could need to change is "w3wp.exe" or "aspnet_wp.exe" depending on your version. Note that I'm assuming you're working with only one w3wp active at a certain point in time. Those of you who have multiple worker processes running simultaneously should feel free to augment the code for your purposes. (Take a look at this to figure out which w3wp to attach to.)

Creating a keyboard shortcut afterwards is pretty easy:



Go to Tools->Options in Visual Studio.  Then just follow those easy steps:
  1. Click on Environment->Keyboard
  2. Type AttachToAspNET in the "Show commands containing" textbox.
  3. Press a keyboard shortcut you want to use.  I used Ctrl-Alt-K and it is working fine.
  4. Click on Assign


Happy coding in 2008!

kick it on DotNetKicks.com

View this post in Russian :)



Hybrid Accordion/TreeView Sitemap

clock December 20, 2007 09:14 by author EtienneT

Live Demo | Source Code (VS 2008) (856.65 kb)

The TreeView site map that we use in FranchiseBlast has become too long to fit reasonably the left panel of our application. We wanted something more compact that would be as simple to use and maintain as our current solution.

Matt Berseth gave us the idea of using an AjaxControlToolkit Accordion to achieve a nice look and feel for our sidebar. Our site map is automatically generated from our Web.sitemap file. (We use different *.sitemap files for each client; we needed something dynamic to cut down on maintenance time. We simply change which *.sitemap file the Web.config points to in our configuration generation scripts.) Furthermore, we also trim what is available in the sidebar according to user roles. I've added a reference to the appropriate web.config settings to achieve this behaviour below.

<siteMap defaultProvider="secureProvider">
<providers>
<add name="secureProvider" type="System.Web.XmlSiteMapProvider" siteMapFile="Web.sitemap" securityTrimmingEnabled="true"/>
</providers>
</siteMap>

Yesterday, I began coding a quick solution to our problem. I was inspired by the code in this post but ultimately I changed it a lot. We wanted all first level nodes in the Web.sitemap to be Accordion panes and all the other levels to be contained in TreeViews inside the parent pane.

We also highlight the current page in bold in the TreeView and display a different pane color to represent the current selection. Altogether, this is pretty simple stuff but hopefully it will help you avoid re-inventing the wheel.

Happy holidays to all!

 

Live Demo | Source Code (VS 2008) (856.65 kb)

kick it on DotNetKicks.com

 

 

 

 

 



A first in the competitive stuff-your-own teddy bear industry

clock December 9, 2007 11:45 by author JKealey

We have just released a new feature on the Teddy Mountain Stuff-Your-Own Teddy Bear Website which we believe is an industry first. Teddy Mountain sees itself as the most innovative teddy bear franchise and they use LavaBlast's technology for both their supporting infrastructure and client facing applications.
We've done a number of industry-specific solutions for this franchisor:

  • Interactive Kiosk with webcam and touch screen to create your own teddy bear adoption certificate.
  • Point of Sale: Integrated with the kiosk, our point of sale is easy to use and reduces training costs.
  • Website: Online sales via an e-commerce engine with a few teddy bear industry-specific features.
  • FranchiseBlast: Our centralized management and collaboration portal which ties everything together, providing a single environment to modify the product line, store pricing, collaborate with others, share documents, view reports, etc.



Today, we augmented the integration between the points of sales distributed across the world and the Teddy Mountain website.  We are now allowing members of the frequent buyer program to view adoption certificates they have created in brick and mortar stores…. online! Simply put, existing PaLS members from a select number of stores are able to see their frequent buyer card balance and birth certificate history on the Teddy Mountain website. We think that no other franchisor in the teddy bear industry has done anything similar and are proud to see Teddy Mountain lead the way. Of course, for privacy concerns, only those who sign-up for the program will have their pictures made available online to distribute to their friends and family.

We feel that, in the long term, this feature will improve gift card sales from out-of-town family members as the donor can receive visual feedback from the recipient, via the Internet.

If the feature attracts some interest, we are open to implementing new features such as integration with FaceBook or using Google's OpenSocial API. We shall also add features such as emailing certificates to friends/family with a greeting.



Debug Visualizer for SubSonic Collections

clock December 7, 2007 20:00 by author EtienneT


Wouldn't it be nice to be able to see a SubSonic collections while you are debugging, just like the DataSet debug visualizer? Because we often need such a tool to debug our SubSonic collections here at LavaBlast, I've created a small Visual Studio Debug Visualizer that you can use to see what your SubSonic collections contain.  How does it work?  While you are debugging, put a breakpoint somewhere and simply hover your mouse over a SubSonic collection variable.  You should see something similar to the screenshot shown above.

Once the tooltip has appeared, you can click on the small magnifier to open the debug visualizer.  You'll see a DataGridView similar to the picture on the right. This will show all your SubSonic objects in a easy to navigate list.  Basically my code takes the SubSonic list and transform it in a DataTable.  I can't use the method ToDataTable() from the SubSonic AbstractList because this requires access to the provider's configuration, and the JIT executing the debug visualizer doesn't have access to it.

To use this simple tool, download this file SubSonicVisualizer.dll (8.00 kb) and put it in your [My Documents]\Visual Studio 2008\Visualizers\ folder, creating the directory if it doesn't already exist. (You might want to double check your file system permissions on this folder, as well.) I compiled this for Visual Studio 2008.  I have also included the source code here (Visual Studio 2008) in case anyone wants to enhance it.

SubSonicVisualizer.zip (386.36 kb)

If you are using Visual Studio 2005, I think this file will work for you, but I have not tested it: SubSonicVisualizer2005.dll (8.00 kb). I simply changed the reference from Microsoft.VisualStudio.DebuggerVisualizers.dll version 9.0 to 8.0 and, from what I have read, it should work in VS.NET 2005.

kick it on DotNetKicks.com


Multitasking while Visual Studio builds

clock December 5, 2007 13:25 by author EtienneT

Are you using Visual Studio and your solutions are taking longer than 10s to build? Why not put those 10s to good use and do something other than stare emptily at your poorly decorated office? Maybe you are worried that your build will finish before you expect it to and you don't want to lose precious time? You don't have to worry about this anymore thanks to what I found today! You can now feel free to peruse a few blog posts while Visual Studio is building!  [insert witty comment about how men have difficulty multi-tasking here]. 

Robert Robins posted this on his blog recently and I didn't even know it existed! You can configure VS.NET build sounds that information you where the build is done!

Go to the Control Panel, Sound and Audio Devices, Sounds Tab, Microsoft Visual Studio, and configure the sounds you'd like to play when the build succeeds/fails. LavaBlast is not responsible for what your coworkers do to you after configuring Pee-wee Herman or a bomb siren as your default sounds.

Happy coding!

 

 

 

 

kick it on DotNetKicks.com


SubSonic Limitations - Part 2 (aka: Knee deep in … SubSonic. )

clock December 4, 2007 22:02 by author JKealey
Knee deep in snow.

After my recent post  asking for the most elegant way to support multiple databases with the same schema at runtime, I received some good pointers in the SubSonic forums from dbr, a forum user. In the end, I admit should have done my homework before posting.

One elegant solution to change the SubSonic Provider/ConnectionString at runtime makes use of SharedDbConnectionScope. I personally do not like this solution, as I prefer my code to explicitly state what it’s doing via its properties or arguments instead of relying on contextual information.  I was also concerned about how it works with regards to concurrency and I did a little digging. Looking at the code, I discovered it internally uses the ThreadStatic attribute which seems like a godsend at first, but further investigation reveals the implementation may be flawed. I did see people complain that it didn’t work for them, but don’t know if it is related to the ThreadStatic attribute. I do not fully trust this technique, but I may wrong as I'm far from an expert in concurrency.

Returning to Dbr's suggestion, he simply generates different providers at runtime for each connection string. This sounds simple if you can manage to modify the ProviderName property on the collection (ActiveList) or object (ActiveRecord) every time you load/save from the database. Without resorting to SharedDbConnectionScope, you can't use the auto-generated constructors because they fall back to the default provider which is hardcoded in the generated object’s schema.

The elegant implementation to encapsulate loading/saving from the database is to use a controller, as would be suggested by the MVC design pattern. I have not yet played with the new MVC templates provided by SubSonic, but we already use a good generic SubSonicController here at LavaBlast.

I wanted to re-write my object loading/saving code using this new solution to get rid of my inelegant concurrency locks. Although obvious in appearance, I encountered a few little hiccups along the way and I thought I'd post my findings here.

Limitation 1: You can't create an object by specifying its ProviderName in an ActiveRecord constructor using the default generated code.

  • Workaround: You need to load it using a collection, which supports the ProviderName.
  • Workaround 2: Use SharedDbConnectionScope
  • Workaround 3: Change the code templates to add new constructors.

Limitation 2: You can't use a collection's Where parameter to load your data (via its primary key or other filter), because of incomplete framework code. Hopefully this will be resolved soon (see issue 13402).

  • Workaround: Copy-paste the code used by internally by the Collection, but pass in the extra ProviderName parameter to the new Query.

Limitation 3: You can't specify the ProviderName property on an ActiveRecord because the setter is marked as protected.

  • Workaround: Change the code templates and add a public method/property that sets PropertyName from within the class.
  • Use SharedDbConnectionScope.

Limitation 4: When you load an ActiveRecord by running a query or by loading a Collection, the ActiveRecord does not inherit the ProviderName from the Collection/Query. This is probably due to Limitation 3.  

My current prototype no longer uses the c# lock keyword. I create instances of a controller, passing in which connection string name to use. All database loading/saving is done via this controller, for which I have attached sample code extracts. I managed to get object loading code to my liking, but I had to resort to SharedDbConnectionScope for saving. Once the minor limitations in the framework are resolved, I will be more comfortable with the code.

In summary, I did manage to get a working prototype and I have attached the relevant portions of code that works with data from the appropriate database (chosen at runtime). Hope this helps!



Month List

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2017

Sign in