<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nico&#039;s CRM &#187; Uncategorized</title>
	<atom:link href="http://blog.nicocrm.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nicocrm.com</link>
	<description>Programming, technology, and CRM - from a Belgian programmer exiled to Missouri</description>
	<lastBuildDate>Sun, 15 Aug 2010 15:57:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SalesLogix Bundle Sort</title>
		<link>http://blog.nicocrm.com/2010/08/15/saleslogix-bundle-sort/</link>
		<comments>http://blog.nicocrm.com/2010/08/15/saleslogix-bundle-sort/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 15:57:43 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=389</guid>
		<description><![CDATA[Published a little utility for sorting items within a SalesLogix bundle (don&#8217;t you hate it when the Architect decides to &#8220;shuffle&#8221; the items you took 20 minutes to arrange?).  I don&#8217;t work that much with the SalesLogix LAN client anymore but this was irritating enough that I had to do something about it.
It is [...]]]></description>
			<content:encoded><![CDATA[<p>Published a little utility for sorting items within a SalesLogix bundle (don&#8217;t you hate it when the Architect decides to &#8220;shuffle&#8221; the items you took 20 minutes to arrange?).  I don&#8217;t work that much with the SalesLogix LAN client anymore but this was irritating enough that I had to do something about it.</p>
<p>It is on the <a href="http://code.msdn.microsoft.com/slxbundlesort">MSDN code gallery</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/08/15/saleslogix-bundle-sort/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft Visual Studio is waiting for an operation to complete</title>
		<link>http://blog.nicocrm.com/2010/08/07/microsoft-visual-studio-is-waiting-for-an-operation-to-complete/</link>
		<comments>http://blog.nicocrm.com/2010/08/07/microsoft-visual-studio-is-waiting-for-an-operation-to-complete/#comments</comments>
		<pubDate>Sat, 07 Aug 2010 19:43:35 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=387</guid>
		<description><![CDATA[This is not an uncommon message&#8230; but I hope this could help someone who is confronted with the same issue I was.
I found I was getting the error every time I started Visual Studio in the morning, with Visual Studio hanging for a looong time&#8230; but not in the afternoon&#8230; crazy uh?  The difference [...]]]></description>
			<content:encoded><![CDATA[<p>This is not an uncommon message&#8230; but I hope this could help someone who is confronted with the same issue I was.</p>
<p>I found I was getting the error every time I started Visual Studio in the morning, with Visual Studio hanging for a looong time&#8230; but not in the afternoon&#8230; crazy uh?  The difference is in the morning I connect to my workstation via remote desktop&#8230; and usually in the afternoon I am physically at the keyboard.  It turns out the delay was caused by the remote desktop clipboard helper&#8230; an application called rdpclip.exe.  Killing the application solved the problem (though it does prevent pasting via remote desktop, obviously, but I can live without that)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/08/07/microsoft-visual-studio-is-waiting-for-an-operation-to-complete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SLX Generic &#8220;Disable Form&#8221; function</title>
		<link>http://blog.nicocrm.com/2010/04/14/slx-generic-disable-form-function/</link>
		<comments>http://blog.nicocrm.com/2010/04/14/slx-generic-disable-form-function/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 21:02:15 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=383</guid>
		<description><![CDATA[This is a generic function to enable / disable all controls on a form from server-side, except for buttons.  Call as LockForm(this, true) or LockForm(this, false).  Watch out as values will be persisted between postbacks (e.g. when browsing through SalesLogix entities).  Also, it won&#8217;t go through a main view tab.


/// &#60;summary&#62;
/// Enable [...]]]></description>
			<content:encoded><![CDATA[<p>This is a generic function to enable / disable all controls on a form from server-side, except for buttons.  Call as LockForm(this, true) or LockForm(this, false).  Watch out as values will be persisted between postbacks (e.g. when browsing through SalesLogix entities).  Also, it won&#8217;t go through a main view tab.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Enable / disable all controls on the form</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="islocked"&gt;&lt;/param&gt;</span>
<span class="kwrd">private</span> <span class="kwrd">void</span> LockForm(Control parent, <span class="kwrd">bool</span> islocked)
{
    <span class="kwrd">foreach</span> (Control c <span class="kwrd">in</span> parent.Controls)
    {
        <span class="kwrd">if</span> (c <span class="kwrd">is</span> IButtonControl || c <span class="kwrd">is</span> SmartPartToolsContainer)
            <span class="kwrd">continue</span>;
        <span class="kwrd">if</span> (c.Controls.Count &gt; 0)
            LockForm(c, islocked);

        PropertyInfo pr = c.GetType().GetProperty(<span class="str">"ReadOnly"</span>);
        <span class="kwrd">if</span> (pr != <span class="kwrd">null</span>)
        {
            pr.SetValue(c, islocked, <span class="kwrd">null</span>);
        }
        <span class="kwrd">else</span>
        {
            pr = c.GetType().GetProperty(<span class="str">"Enabled"</span>);
            <span class="kwrd">if</span> (pr != <span class="kwrd">null</span>)
            {
                pr.SetValue(c, !islocked, <span class="kwrd">null</span>);
            }
        }
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/04/14/slx-generic-disable-form-function/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sorted SLX Lookup</title>
		<link>http://blog.nicocrm.com/2010/04/08/sorted-slx-lookup/</link>
		<comments>http://blog.nicocrm.com/2010/04/08/sorted-slx-lookup/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 18:56:03 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=372</guid>
		<description><![CDATA[One little &#8220;nicety&#8221; of the lookups in the web client is we no longer have to add a fake condition to force them to populate when they are open &#8211; one can simply add an &#8220;InitializeLookup=true&#8221; parameter to obtain that effect.
Unfortunately there is a serious usability drawback in the current version &#8211; the records are [...]]]></description>
			<content:encoded><![CDATA[<p>One little &#8220;nicety&#8221; of the lookups in the web client is we no longer have to add a fake condition to force them to populate when they are open &#8211; one can simply add an &#8220;InitializeLookup=true&#8221; parameter to obtain that effect.</p>
<p>Unfortunately there is a serious usability drawback in the current version &#8211; the records are not sorted by default.  So if there are more than a handful of them the user still has to click on the search button to get them to sort, which defeats the purpose of getting the lookup to pre-populate.</p>
<p>You can fix the problem in several ways.  The first is to add a little piece of javascript in your code behind to force the sort&#8230; this is rather unobtrusive and easy to test so if you are only fixing one form it&#8217;s probably the way to go:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
ScriptManager.RegisterStartupScript(<span class="kwrd">this</span>, GetType(), Guid.NewGuid().ToString(),
            <span class="str">"$(document).ready(function() {"</span> +
            lueLinkOpp.ClientID + <span class="str">@"_luobj.initGrid = function (seedValue, reload) {
                LookupControl.prototype.initGrid.apply(this, [seedValue, reload]);
                this.getGrid().getNativeGrid().getStore().setDefaultSort('CreateDate');
            }
            });
            "</span>, <span class="kwrd">true</span>);
</pre>
<p>It looks pretty yucky, but hey, it works.</p>
<p>If there are more than a handful of lookups, or if you want the changes to apply also on QuickForms, you&#8217;ll probably want to package them into a user control, something like this:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> FixSlxLookup : LookupControl
{
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Add the sorting hack.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;param name="e"&gt;&lt;/param&gt;</span>
    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPreRender(EventArgs e)
    {
        <span class="kwrd">base</span>.OnPreRender(e);
        <span class="kwrd">if</span> (InitializeLookup &amp;&amp; LookupProperties.Count &gt; 0)
        {
            ScriptManager.RegisterStartupScript(<span class="kwrd">this</span>, GetType(), Guid.NewGuid().ToString(),
                <span class="str">@"$(document).ready(function() { setTimeout(function() {
                    "</span> + <span class="kwrd">this</span>.ClientID + <span class="str">@"_luobj.initGrid = function(seedValue, reload) {
                        LookupControl.prototype.initGrid.apply(this, [seedValue, reload]);
                        this.getGrid().getNativeGrid().getStore().setDefaultSort('"</span> + <span class="kwrd">this</span>.LookupProperties[0].PropertyName + <span class="str">@"');
                    };
                }, 500) });"</span>, <span class="kwrd">true</span>);
        }
    }
}</pre>
<p>Once you place the control in your own assembly, one tiny problem remains &#8211; by default the lookup control will try to locate the image for the button in the containing assembly.  So you need to adjust that in order to make it look in the original SalesLogix assembly:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Initialize the lookup image if necessary</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="e"&gt;&lt;/param&gt;</span>
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnInit(EventArgs e)
{
    <span class="kwrd">base</span>.OnInit(e);
    <span class="rem">// Fix the image - by default the SLX controls tries to load it from the current type's assembly.</span>
    <span class="rem">// since this is a subclass of LookupControl it is not in the "correct" assembly anymore.</span>
    <span class="rem">// this fix ensures that the image is loaded from the original assembly</span>
    <span class="kwrd">if</span> (<span class="kwrd">this</span>.ViewState[<span class="str">"LookupImageURL"</span>] == <span class="kwrd">null</span>)
        LookupImageURL = <span class="kwrd">this</span>.Page.ClientScript.GetWebResourceUrl(<span class="kwrd">typeof</span>(LookupControl), <span class="str">"Sage.SalesLogix.Web.Controls.Resources.Find_16x16.gif"</span>);
}</pre>
<p>If you want to have it used in QuickForms you&#8217;ll have to adjust the QuickForm template &#8211; there is an example of how to do that in a <a href="http://blog.nicocrm.com/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/">previous article</a>.</p>
<p>The fixed lookup is available as part of <a href="http://github.com/nicocrm/OpenSlx">OpenSlx</a>, but it just has the 2 above functions so you can simply rip those instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/04/08/sorted-slx-lookup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenSlx Library</title>
		<link>http://blog.nicocrm.com/2010/03/22/openslx-library/</link>
		<comments>http://blog.nicocrm.com/2010/03/22/openslx-library/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 16:54:13 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=348</guid>
		<description><![CDATA[Just wanted to do a quick post to introduce the OpenSlx library I mentioned in the previous post about SimpleLookup.  The library is available from GitHub at http://github.com/nicocrm/OpenSlx.  It is free to use in your own customizations, or you can rip code out of it and put it into your own stuff, though [...]]]></description>
			<content:encoded><![CDATA[<p>Just wanted to do a quick post to introduce the OpenSlx library I mentioned in the previous post about SimpleLookup.  The library is available from GitHub at <a href="http://github.com/nicocrm/OpenSlx">http://github.com/nicocrm/OpenSlx</a>.  It is free to use in your own customizations, or you can rip code out of it and put it into your own stuff, though as it is placed under the GPL license there are a few limitations:</p>
<ul>
<li>you can take the OpenSlx library, modify it, and redistribute it as part of a customization, without having to publish it (though you would have to make the source code available to the customer, at their request, which is the usual business model anyway).  The same apply to ripping out code &#8211; you can rip the code and put it into your own customizations, without having to publish those (other than to the user of the code, i.e. the customer &#8211; this does not include the actual end users, either SalesLogix users, or their own customers accessing SalesLogix via customer portal)</li>
<li>you can take the OpenSlx library, unmodified, and include it as part of a proprietary component &#8211; you would have to make available any modification you make to OpenSlx, or any derived work (e.g. if you were to create a subclass), but other parts of your package would not be affected</li>
<li>you can&#8217;t take the OpenSlx library, add some controls to it (or fix some of the existing ones), and resell it as a proprietary component &#8211; this is the kind of change that I hope would be redistributed</li>
<li>you can&#8217;t rip some code from the OpenSlx library, and include it into your own, proprietary component which you resell as a software package &#8211; you have to leave the code separated.  However you can rip some code, and include it into your own open source components &#8211; they will have to be released under the GPL as well, though</li>
</ul>
<p><b>2010-06-27</b>: I changed the license to Apache, so most of the restrictions above do not hold anymore, even though I still hope that you would contribute improvements back to OpenSlx.  Without getting into details, this was the only practical way for me to be able to keep contributing to the code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/03/22/openslx-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Lookup &#8211; for Slx Web</title>
		<link>http://blog.nicocrm.com/2010/03/15/simple-lookup-for-slx-web/</link>
		<comments>http://blog.nicocrm.com/2010/03/15/simple-lookup-for-slx-web/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 21:31:33 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=341</guid>
		<description><![CDATA[This is going to be another quickie because I am in a hurry!
One of the most boring tasks when creating custom smart parts is setting up the lookups.  There is next to no help from intellisense, so it takes a while to get right in the first place, but worse than that, if the [...]]]></description>
			<content:encoded><![CDATA[<p>This is going to be another quickie because I am in a hurry!</p>
<p>One of the most boring tasks when creating custom smart parts is setting up the lookups.  There is next to no help from intellisense, so it takes a while to get right in the first place, but worse than that, if the user wants to add a column to a lookup you have to go through ALL the forms that have that lookup and add it by hand (this is actually a problem with QuickForms too, not just custom smart part).  What a huge usability setback from the LAN client where they can just design their lookups in the Administrator.</p>
<p>In order to (partly) remedy that I created a component called &#8220;SimpleLookup&#8221; that runs through the Lookup table meta-data and populates the LookupProperties collection accordingly.  So basically you create the lookup as:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">OpenSlx:SimpleLookup</span> <span class="attr">LookupName</span><span class="kwrd">="ACCOUNT:ACCOUNT"</span>
   <span class="attr">LookupEntityName</span><span class="kwrd">="Account"</span> <span class="attr">ID</span><span class="kwrd">="lueAssignDistributor"</span>
   <span class="attr">LookupBindingMode</span><span class="kwrd">="String"</span> <span class="attr">AutoPostBack</span><span class="kwrd">="true"</span>
   <span class="attr">LookupEntityTypeName</span><span class="kwrd">="Sage.SalesLogix.Entities.Account, Sage.SalesLogix.Entities"</span>
   <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;</span></pre>
<p>The LookupName part is the important part &#8211; you can either put the Lookup Name (as defined in the lookup manager) or the search field (similar to how we used to reference lookups in the LAN client).  Now when you want to add a column you can add it in the familiar lookup manager (though it is cached for efficiency so it may still not show up for a few minutes or until the application pool is recycled).</p>
<p>This SimpleLookup is part of a growing collection of components that I am able to make available as open source &#8211; it is available on GitHub at <a href="http://github.com/nicocrm/OpenSlx">http://github.com/nicocrm/OpenSlx</a>, along with a few other pieces like the <a href="http://blog.nicocrm.com/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/">SimplePicklist</a> I blogged about before.  Note that it won&#8217;t handle the more exotic lookup definitions (in particular any link used in the lookup must also be defined as a relationship in the Application Architect) so be sure to test the particular configuration.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/03/15/simple-lookup-for-slx-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Validation of SalesLogix Lookup Controls</title>
		<link>http://blog.nicocrm.com/2010/03/08/validation-of-saleslogix-lookup-controls/</link>
		<comments>http://blog.nicocrm.com/2010/03/08/validation-of-saleslogix-lookup-controls/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 23:44:22 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=333</guid>
		<description><![CDATA[OK so I am really, really loving JQuery lately.  This is a neat use of how to add a custom validator for a lookup control in SalesLogix.  The lookups have this &#8220;Required&#8221; property which you can turn on to make them required, but this has 2 major flaws:

Can&#8217;t specify the validation group, in [...]]]></description>
			<content:encoded><![CDATA[<p>OK so I am really, really loving JQuery lately.  This is a neat use of how to add a custom validator for a lookup control in SalesLogix.  The lookups have this &#8220;Required&#8221; property which you can turn on to make them required, but this has 2 major flaws:</p>
<ul>
<li>Can&#8217;t specify the validation group, in case you want the lookup to only be validated in certain cases</li>
<li>More importantly, can&#8217;t specify an error message, so you are left with the default tiny-ish red asterisk.  I don&#8217;t know about you but I like my error message to be big, bold, and explicit.</li>
</ul>
<p>So we have this RequiredFieldValidator, part of the standard ASP.NET controls.  This is so handy for validating textboxes but if you try to have it validate a lookup you will get this beautiful error message:</p>
<p><code>Control 'luePurchContact' referenced by the ControlToValidate property of '' cannot be validated.</code></p>
<p>There is a customvalidator that lets you specify your own validation function, and you can do that.  This would look something like:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
 <span class="kwrd">&lt;</span><span class="html">asp:CustomValidator</span> <span class="attr">ID</span><span class="kwrd">="CustomValidator2"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">ValidationGroup</span><span class="kwrd">="SubmitCredit"</span> <span class="attr">Text</span><span class="kwrd">="*"</span> <span class="attr">OnServerValidate</span><span class="kwrd">="luePurchContact_Validate"</span>
                <span class="attr">ErrorMessage</span><span class="kwrd">="Please select Purchasing Contact"</span><span class="kwrd">/&gt;</span></pre>
<p>and then in the code behind:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
    <span class="kwrd">void</span> luePurchContact_Validate(<span class="kwrd">object</span> source, ServerValidateEventArgs args)
    {
        args.IsValid = (luePurchContact.LookupResultValue != <span class="kwrd">null</span>);
    }</pre>
<p>The big problem here is that this requires a postback.  Postbacks are slow.  You want to avoid them as much as possible.  They waste bandwidth, server CPU, client CPU, they look ugly, they cause the control focus to be lost, and they mess up Javascript customizations.  They suck.  Furthermore, if some controls require a postback to validate, and some don&#8217;t, the users will only get a partial validation at a time, which is annoying.  </p>
<p>Anyway, Microsoft thought the same thing of postbacks, and they provided an extension to these customvalidators that let you do the validation in Javascript.  So the only difficulty is, how do we retrieve the lookup&#8217;s value in Javascript?  It&#8217;s very easy if you know the client id, but ASP.NET has this nasty tendency to mangle those.  Not a big deal though, as JQuery is still able to find controls based on the last characters of the id (assuming there is no other control with that same id in the page).  This lets me write the following for validation:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">asp:CustomValidator</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">ValidationGroup</span><span class="kwrd">="SubmitCredit"</span> <span class="attr">Text</span><span class="kwrd">="*"</span>
 <span class="attr">ErrorMessage</span><span class="kwrd">="Please select Purchasing Contact"</span>
 <span class="attr">ClientValidationFunction</span><span class="kwrd">="(function(s, e) { e.IsValid = !!$('input[id$=luePurchContact_LookupResult]').val(); })"</span> <span class="kwrd">/&gt;</span></pre>
<p>If you are suspicious about another lookup with the same id on another part of the page, use the following instead:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">id</span><span class="kwrd">="frmAccCredit"</span><span class="kwrd">&gt;</span>
<span class="rem">&lt;!-- </span>
<span class="rem">  "frmAccCredit" would be a unique identifier for the form.</span>
<span class="rem">  You can use anything that is going to be unique, and put it at top level of the form.</span>
<span class="rem">  This is also handy for designing css rules that should not affect other</span>
<span class="rem">  parts of the page.</span>
<span class="rem">--&gt;</span>

...
more stuff
...

<span class="kwrd">&lt;</span><span class="html">asp:CustomValidator</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">ValidationGroup</span><span class="kwrd">="SubmitCredit"</span> <span class="attr">Text</span><span class="kwrd">="*"</span>
 <span class="attr">ErrorMessage</span><span class="kwrd">="Please select Purchasing Contact"</span>
 <span class="attr">ClientValidationFunction</span><span class="kwrd">="(function(s, e) { e.IsValid = !!$('#frmAccCredit input[id$=luePurchContact_LookupResult]').val(); })"</span> <span class="kwrd">/&gt;</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2010/03/08/validation-of-saleslogix-lookup-controls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step by Step Guide to Custom Form Development with Visual Studio</title>
		<link>http://blog.nicocrm.com/2009/12/15/step-by-step-guide-to-custom-form-development-with-visual-studio/</link>
		<comments>http://blog.nicocrm.com/2009/12/15/step-by-step-guide-to-custom-form-development-with-visual-studio/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 03:33:41 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.nicocrm.com/?p=301</guid>
		<description><![CDATA[I think I just made the longest post ever on the SalesLogix Journal.  It is a fairly complete guide on how to get started writing custom smart parts for SalesLogix in Visual Studio.  I think it is a bit scary to get started with those but it is a must to provide rich [...]]]></description>
			<content:encoded><![CDATA[<p>I think I just made the longest post ever on the <a href="http://community.sagesaleslogix.com/t5/The-Sage-SalesLogix-Journal/Step-by-Step-Guide-to-Custom-Form-Development-with-Visual-Studio/ba-p/7548">SalesLogix Journal</a>.  It is a fairly complete guide on how to get started writing custom smart parts for SalesLogix in Visual Studio.  I think it is a bit scary to get started with those but it is a must to provide rich functionality (for better or worse &#8211; but I think it is a good thing that Sage is not trying to cram every possible functionality into the QuickForms &#8211; their job is not to create a Visual Studio replacement!!)</p>
<p>Anyway, I might start writing most of the SalesLogix content through that channel so this blog does not look so much like a SalesLogix reference guide <img src='http://blog.nicocrm.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2009/12/15/step-by-step-guide-to-custom-form-development-with-visual-studio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Picklist &#8211; Enabling Picklist manager options for the web client</title>
		<link>http://blog.nicocrm.com/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/</link>
		<comments>http://blog.nicocrm.com/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 22:53:25 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.chivinou.net/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/</guid>
		<description><![CDATA[One missing feature of the SLX web client some of our users have been very vocal about is the ability to manage picklist options (multi-select, alphabetical sort, etc) from the good old picklist manager.&#160; What makes it even more confusing is that there is no indication in the picklist manager that the options are not [...]]]></description>
			<content:encoded><![CDATA[<p>One missing feature of the SLX web client some of our users have been very vocal about is the ability to manage picklist options (multi-select, alphabetical sort, etc) from the good old picklist manager.&#160; What makes it even more confusing is that there is no indication in the picklist manager that the options are not actually going to take effect… but in fact in the web client these options are only taken from the picklist control itself (i.e., set via the App Architect or in the page’s code).&#160; </p>
<p>Fortunately it is a reasonably simple problem to resolve since those picklist options are readily accessible from the database.&#160; All we have to do really is wrap the creation of the picklist control with something that will know how to pull that info and set it on the control.&#160; The simplest way to do that would probably be to subclass the control, but I decided to go with a decorator pattern instead (the idea was that this would let me change a bit more of the behavior, for example, replace the stock picklist with a regular dropdown).&#160; So instead of using:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">SalesLogix:PickListControl</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">ID</span><span class="kwrd">=&quot;pklType&quot;</span> <span class="attr">PickListName</span><span class="kwrd">=&quot;Account Type&quot;</span> <span class="attr">AutoPostBack</span><span class="kwrd">=&quot;true&quot;</span>  <span class="attr">AlphaSort</span><span class="kwrd">=&quot;true&quot;</span> <span class="attr">MustExistInList</span><span class="kwrd">=&quot;true&quot;</span> <span class="attr">AllowMultiple</span><span class="kwrd">=&quot;true&quot;</span>  <span class="kwrd">/&gt;</span></pre>
<p>I use:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">SSS:SimplePickList</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">ID</span><span class="kwrd">=&quot;pklType&quot;</span> <span class="attr">PickListName</span><span class="kwrd">=&quot;Account Type&quot;</span> <span class="attr">AutoPostBack</span><span class="kwrd">=&quot;true&quot;</span>   <span class="kwrd">/&gt;</span></pre>
<p>Behind the scene the SimplePicklist controls reads the attributes from the database and create a Saleslogix picklist control with the proper settings, something like this:</p>
<pre class="csharpcode">_picklist = <span class="kwrd">new</span> PickListControl();
<span class="kwrd">if</span> ((_storageMode &amp; PicklistStorageMode.Id) != 0)
    _picklist.StorageMode = Sage.Platform.Controls.StorageModeEnum.ID;
<span class="kwrd">else</span> <span class="kwrd">if</span> ((_storageMode &amp; PicklistStorageMode.Code) != 0)
    _picklist.StorageMode = Sage.Platform.Controls.StorageModeEnum.Code;
_picklist.PickListName = _picklistName;
_picklist.AllowMultiples = _attr.AllowMultiples;
_picklist.AlphaSort = _attr.AlphaSorted;
_picklist.NoneEditable = _attr.NoneEditable;
_picklist.Required = _attr.Required;
_picklist.MustExistInList = _attr.ValueMustExist;
_picklist.PickListValueChanged += <span class="kwrd">delegate</span>
{
    <span class="kwrd">if</span> (TextChanged != <span class="kwrd">null</span>)
        TextChanged(<span class="kwrd">this</span>, EventArgs.Empty);
};
parentControl.Controls.Add(_picklist);</pre>
<p>This works fine for custom smart parts, how about for QuickForms?&#160; Well, it is possible to change the template there too, but as it is global (will affect nearly every picklist in the client) it is a bit scarier <img src='http://blog.nicocrm.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>In the Model\QuickForms\Web\QFSLXPickList.WebControlRenderingTemplate.vm I changed the control to use my “SimplePickList” instead of a PickListControl </p>
<pre class="csharpcode">## Simple Picklist alternative (to automatically determine the sort etc)
    <span class="kwrd">&lt;</span><span class="html">SSS:SimplePickList</span> Compatible=&quot;true&quot; <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">ID</span><span class="kwrd">=&quot;${qfcontrol.ControlId}&quot;</span> #<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">IsReadOnly</span>)<span class="attr">ReadOnly</span><span class="kwrd">=&quot;true&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>(!$<span class="attr">qfcontrol</span>.<span class="attr">Enabled</span>)<span class="attr">Enabled</span><span class="kwrd">=&quot;false&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">ToolTip</span> != <span class="kwrd">&quot;&quot;</span>) <span class="attr">ToolTip</span><span class="kwrd">=&quot;&lt;%$ resources: ${qfcontrol.ControlId}.ToolTip %&gt;&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">HotKey</span> != <span class="kwrd">&quot;&quot;</span>)<span class="attr">AccessKey</span><span class="kwrd">=&quot;$qfcontrol.HotKey&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">PickListName</span> != <span class="kwrd">&quot;&quot;</span>)<span class="attr">PickListName</span><span class="kwrd">=&quot;$qfcontrol.PickListName&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">HasActionCode</span> || $<span class="attr">qfcontrol</span>.<span class="attr">AutoPostBack</span>)<span class="attr">AutoPostBack</span><span class="kwrd">=&quot;true&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">Required</span>)<span class="attr">Required</span><span class="kwrd">=&quot;true&quot;</span> #<span class="attr">end</span>
#<span class="attr">if</span>($<span class="attr">qfcontrol</span>.<span class="attr">MaxLength</span> <span class="kwrd">&gt;</span> 0)MaxLength=&quot;$qfcontrol.MaxLength&quot; #end
#if($qfcontrol.TabIndex <span class="kwrd">&gt;</span> 0)TabIndex=&quot;$qfcontrol.TabIndex&quot; #end
#if($qfcontrol.StorageMode != &quot;Text&quot;)StorageMode=&quot;$qfcontrol.StorageMode&quot; #end
#if($qfcontrol.StyleScheme != &quot;&quot;)CssClass=&quot;$qfcontrol.StyleScheme&quot; #end
#if(!$qfcontrol.Visible)Visible=&quot;false&quot; #end  <span class="kwrd">/&gt;</span></pre>
<p>The “Compatible=true” setting is something I added to avoid bad surprises – it forces the list to display as a standard Saleslogix picklist, instead of e.g. a dropdown.</p>
<p>Now because it is a custom control, it requires a change to web.config too, something like this (under system.web/pages/controls):</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">tagPrefix</span><span class="kwrd">=&quot;SSS&quot;</span> <span class="attr">namespace</span><span class="kwrd">=&quot;SSSWorld.Slx75.Web.Controls&quot;</span> <span class="attr">assembly</span><span class="kwrd">=&quot;SSSWorld.Slx75&quot;</span><span class="kwrd">/&gt;</span></pre>
<p>I think it works great, but haven’t tried on a production system yet &#8211; I am going to save it for a next big project when I can get a resource to QA the entire app!&#160; I do already use the “small” version in production in my custom smart parts, though.&#160; I saved the code under <a href="http://blog.chivinou.net/media/SimplePicklist-20091005.zip">here</a>, if interested feel free to rip it up (though it probably has some extra dependencies so it will require a bit of cleanup).</p>
<p>So although I think the PickListControl should support this out of the box it is nice to see that it is not too hard to add the functionality ourselves.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2009/10/05/simple-picklist-enabling-picklist-manager-options-for-the-web-client/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Display user lookup as a dropdown (legacy-web style)</title>
		<link>http://blog.nicocrm.com/2009/09/01/display-user-lookup-as-a-dropdown-legacy-web-style/</link>
		<comments>http://blog.nicocrm.com/2009/09/01/display-user-lookup-as-a-dropdown-legacy-web-style/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 18:44:16 +0000</pubDate>
		<dc:creator>Nicolas Galler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.chivinou.net/2009/09/01/display-user-lookup-as-a-dropdown-legacy-web-style/</guid>
		<description><![CDATA[Our users upgraded from 7.0 to 7.5 complained about the user lookup dialog – on 7.0 it used to be a dropdown, whereas on 7.5 it’s a popup similar to the LAN client. 
 
Sorry for the chopped image, I had to hide the name and was too lazy to re-run on the eval db.
 [...]]]></description>
			<content:encoded><![CDATA[<p>Our users upgraded from 7.0 to 7.5 complained about the user lookup dialog – on 7.0 it used to be a dropdown, whereas on 7.5 it’s a popup similar to the LAN client. </p>
<p><a href="http://blog.chivinou.net/wp-content/uploads/2009/09/image2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chivinou.net/wp-content/uploads/2009/09/image-thumb2.png" width="244" height="202" /></a> </p>
<p>Sorry for the chopped image, I had to hide the name and was too lazy to re-run on the eval db.</p>
<p> The problem is the popup takes a couple seconds to come up on IE7, sometimes more on slow machines or slow connections &#8211; it’s a bit irritating.&#160; After a brief phase of denial (how dare they refuse the New and Improved way, etc) I set to work.&#160; Had to struggle a bit with the combination of available properties but finally got it working.&#160; Configuring lookup is definitely a big pain on the web client!&#160; This is the winning combo:</p>
<ul>
<li>Display Mode = DropDownList</li>
<li>Display Property = UserInfo.UserName</li>
<li>Lookup Entity Name = User</li>
<li>Lookup Binding Mode = Object</li>
<li>In the Lookup Pre Filters, add a filter on “Enabled” (make sure the property is populated as System.Boolean, and set OperatorCode to &#8220;=&#8221;) and filter value of “true”</li>
</ul>
<p>The DropDown style lookups are a bit more picky on the parameters than the regular lookup, because they actually use NHibernate parameters instead of inline HQL.&#160; In general I would say it is a good thing to use parameters, though in this case it makes it a bit harder for us to hack around the limitation of the control. </p>
<p>Data binding works fine, the only big problem I have found is that it sorts by first name instead of last name for some reason (which you can’t really see in the screen shot as I removed the last name but you can imagine).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nicocrm.com/2009/09/01/display-user-lookup-as-a-dropdown-legacy-web-style/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
