Tuesday, December 6, 2005

Changing Custom Validator Messages

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/changing_custom_validator_messages.htm]

Sometimes you may want to have one custom validator potentially display two different error messages depending on context. For example you may make your own date validator (perhaps to work with your own custom calendar control), and this control may first validate format ("xyz" is not a date, "12/3/2005" is), and then validate integration with the rest of the page ("Start Date occurs before End Date"). Each type of validation merits its own message. The reason you'd combine these controls is because the integration requires first performing the type validation.

Ideally we could change this at both the client and the server. We can do this with ASP 1.1's validators.

We can set the error message at the client via using the source.errormessage property:

function ValidateStuff(source, arguments)
{
    source.errormessage = "I changed this on the fly!"; //or source.errormessageB
    arguments.IsValid = false;
}

We can set the error message at the server via casting the source object and setting its ErrorMessage.

protected void ValidateMaxLength (object source, ServerValidateEventArgs value)
{
    ((CustomValidator)source).ErrorMessage = "This was changed at the server";
    value.IsValid = false;
}

We can access the other error message simply by adding a attribute to the current validtor, like ErrorMessageB, and then referencing it like source.errormessageB. Check out Validation Tips for Validators for more details about this.

If you have two error messages, you'll want separate properties for each of those, i.e. have messageA and messageB. Then set source.errormessage to the appropriate one. Don't store your main message in source.errormessage because it will just get overwritten when you set it with something else.

Note that in order for this to show up, the error messages must be displayed in a ValidationSummary control.

A sample custom validator Html might be:


...
ErrorMessage="CustomValidator"
ErrorMessage_A = "..."
ErrorMessage_B = "..."

ControlToValidate="Text1"
ClientValidationFunction="ValidateDate"
OnServerValidate="ValidateDate"
Display="None">

This is just another trick for ASP.Net validators to give you some more flexibility.

Tuesday, November 29, 2005

DHTML II: Using Hidden Divs instead of Popup windows

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/dhtml_ii_using_hidden_divs_instead_of_popup_windows.htm]

Previous on DHTML: DHTML I: Intro and Positioning Text

A common UI problem is wanting to display a small amount of information (like a date) that takes a big UI control to generate (like a calendar). The standard solution to this is to make some sort of sub-window where the user has as much real-estate as needed to get that information. Two ways to implement this are (1) a new browser popup window, (2) hidden divs.

Each has their own pros & cons. Popup windows are pretty standard and relatively cross-browser dependable. Recall that you can open a popup like so:

window.open("Window.aspx","Name1",'toolbar=no,location=no ...');

Popup windows have several disadvantages:

  • It's hard to get data to and from them (you can pass data to them through the querystring, and from them with the window.opener property, but this is messy).
  • You can't control where the user drags them. They can hide them behind other windows, move them all over, max or min them, etc.. To some extent you can pile on the JavaScript to minimize what the user can do, but it gets tedious.
  • They open up a whole separate application (i.e. a new browser)

A whole different solution is to use a hidden div, and perhaps enclosing an iFrame to present a whole new page. This gives you the benefits of a popup (more temporary real-estate), without the drawbacks.

We can implement this using CSS's visibility style, along with the positioning attributes. Here's a sample how:

<html>
  <head>
    <title>SimplePopuptitle>
    <style>
      .divAbsPosition1
      {
        z-index: 1;
        left: 100px;
        position:absolute;
        top: 50px;
      }
    style>
  head>
  <body MS_POSITIONING="FlowLayout">
   
    <form id="Form1" method="post" runat="server">

    <div id="DivAbsPosition" class="divAbsPosition1" style="COLOR: black">
      <table border="1" bgcolor=#ffffcc>
        <tr>
          <td>Whatever content you want goes here.td>
        tr>
      table>
    div>
      <input type=button value="Show"
        onclick="document.getElementById('DivAbsPosition').style.visibility='visible'" />
      <input type=button value="Hide"
        onclick="document.getElementById('DivAbsPosition').style.visibility='hidden'" />
      <p>Some normal page content goes here.p>
      <p>Some normal page content goes here.p>
     form>
  body>
html
>

This technique is another great benefit of DHTML. It's very useful when writing your own custom control (such as a dropdown or calendar) or making appropriate popups.

Sunday, November 27, 2005

DHTML I: Intro and Positioning Text

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/dhtml_i_intro_and_positioning_text.htm]

HTML is essentially static. However with some JavaScript and CSS, you can make it dynamic - hence DHTML (D is for Dynamic). There are lots of neat things you can do with DHTML. While some of it may just be for "toys", some of it can also enhance the UI for an enterprise app.

Using CSS, you can position your text in several ways. First you can set whether the style refer to an absolute or relative position. You can then specify the left or top. You can also specify the "layer" via the Z index. For example, the following snippet offsets the div tag:

  <style>
    .pos1
    {
      z-index: 1;
      left: 100px;
      position:absolute;
      top: 20px;
      background-color:Yellow;
    }
  style>
  head>
  <body MS_POSITIONING="FlowLayout">
    <form id="Form1" method="post" runat="server">
      <div class="pos1">
      Hello World
      div>
     form>
  body>

You can use JavaScript to programmatically change the CSS class as whole, or switch a specific style:

document.getElementById('DivPosition').className = 'myNewClass';
document.getElementById('DivPosition').style.left = 10;

The combination of all these things opens up a lot of possibilities. For example, using a JavaScript timer, you could move a div across the page by continually updating the .left property.

The next several posts will dive more into DHTML.

Monday, November 21, 2005

Implementing a timer in JavaScript with setTimeout

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/implementing_a_timer_in_javascript_with_settimeout.htm]

Sometimes you want something cycling in the background to give your page an active feel, like images or text labels updating every 4 seconds. You can do that with the JavaScript setTimeout function. The script below keeps a running clock:

<html>
  <head>
    <script language=javascript>
   

    script>
  head>
  <body MS_POSITIONING="FlowLayout" onload="UpdateCycle()">
    <form id="Form1" method="post" runat="server">
      This is a timer test.
      <span id="Span1">span>
    form>
  body>
html
>

This method takes a method to call, and the time (in milliseconds) to wait. The pattern is simple:

  1. Have the body onload event call the looping function, like UpdateCycle(). This function manages the cycling.
  2. Have the looping function call whatever action you want, and the setTimeOut method.
  3. Implement the action method (in this case SetTime) to do whatever action you need.

You could even make a global variable, increment it in each UpdateCycle, and therefore keep a global counter of how many cycle have passed. You could also have the body onload call an initialization method instead, that method would do start-up initialization, and then call the UpdateCycle method.

This is a simple JavaScript method to use, but it can have a big return to help certain pages feel more lively.

Sunday, November 20, 2005

Setting the DOS ErrorLevel

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/setting_the_dos_errorlevel.htm]

Programs can return an errorLevel. Batch scripts can then access than using %ErrorLevel%, and then use this in the flow of the script. For example, if program X returns a certain errorLevel, the script can take a specific path. Convention is that an errorLevel of 0 is "Success", and anything else is some kind of failure.

This is not to be confused with creating an environmental variable named "ErrorLevel". Setting the environmental variable does not update the batch script's error level itself. This becomes apparent when using another tool that checks the script errorLevel. For example, in NAnt you can execute batch scripts and specify the build to fail if there's an error in the batch. However, you'll notice (at least in version .84) that setting the errorLevel as an environmental variable won't cause the script to fail, but having an exe fail will.

We want the option of setting the errorLevel from an environmental variable, not just through an exe. We can do this by writing a trivial console app:

[STAThread]
static int Main(string[] args)
{
      int i = 0;
      try
      {
         i = Convert.ToInt32(args[0]);
      }
      catch
      {
        Console.WriteLine("Error info...");
      }
      return i;
}

This takes a single argument from the command line, converts it to an integer, and then returns that value as the program error code. Note that console apps need not return "void", as is the template default. They can return int precisely for this purpose.

We can then call this program, passing in some parameter from DOS, and it will set the errorLevel. You'll notice that this would cause the NAnt build to fail. Also note that this call must be the every last line of the batch - not even an ECHO or REM after it.

Confusing the environmental errorLevel and DOS script's errorLevel is an easy and understandable mistake, and fortunately it has an easy and understandable solution.

Monday, November 14, 2005

Random DOS Nuances: for-loops, params, and if-blocks

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/random_dos_nuances_forloops_params_and_ifblocks.htm]

I've blogged some tips on DOS before, but here are some more. One of my coworkers (thanks Roey) pointed out several DOS nuances that I found useful - they're the kind of things that are easy to miss:

Use single % for parameters (like %1), double %% for variables (like %myVar%)

While you can use environmental variables using the percent signs like so: %myVar%, parameters only have the first percent, like so: %1. What's tedious is if you make it %1%, you may be able to get away with it in some cases. But if you put two parameters on the same like like %1...%2, then you need to get it straight.

Set operators within an if-block don't update until after the if-block finishes

In a language like C#, you could both update the variable, and then use that variable within the same if-block. Apparently you can't do that in DOS.

REM: Won't work:
If 0 EQU 0 (
    set outputFile="ABC"
    Echo Value: %outputFile%
)

You need to let the if-block finish first. You can do this by putting the set operation in its own block, either like this:

REM: WIll work:
If 0 EQU 0 (
set outputFile="ABC"
)
Echo Value: %outputFile%

or like this:

REM: will also work:
If 0 EQU 0 set outputFile="ABC"
If 0 EQU 0 Echo Value: %outputFile%

DOS for-loops in a batch script require an extra '%' in front of the variable.

This will fail:

Rem start loop:
for /F %a in (C:\temp\List.txt) do Echo %a
Pause

This will work:

Rem start loop:
for /F %%a in (C:\temp\List.txt) do Echo %%a
Pause

This last one is especially tedious to debug because if you copy the contents of the script to a command window to run it, then it suddenly works.
 

Thursday, November 10, 2005

Chicago .Net Launch

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/chicago_net_launch.htm]

I just got back from the Chicago .Net Launch, and it was very impressive. It looks like Microsoft is releasing new products for the entire enterprise spectrum. I'm especially interested in the new Visual Studio and Team System that finally makes it easy to build good development process, and the new features of ASP.Net. I also had some great experiences with the ask-the-experts. The Microsoft guys were on as usual, but the non-Microsoft experts were great too. In particular, Jon Henning of DotNetNuke nailed a bunch of my ASP questions. I also stopped at maybe 50 different vendor booths to see every kind of tool and service in the .Net ecosphere. A good day all around.