Tuesday, October 27, 2009

Collapsible javascript

I believe this should work with all browsers when added to the onClick handler of what you want to trigger it. Set the div, span, etc. to have an initial display of one of the two for a fresh page load. Also I selected inline, your application may prefer block for some parts.

<script type="text/javascript">

    function ShowHide(id) {

    
var elementStyle=document.getElementById(id).style

    elementStyle.display = elementStyle.display ==
"inline" ? "none" : "inline";

}


Example:


<h2>

<span onclick="ShowHide('SessionVarHider');">Session</span><span style="display:none" id="SessionVarHider"> -

</h2>


  <ul id="sessionVars">

      <!--<li><a href="#">Aliquam libero</a></li>-->

      <%= SessionVariableList() %>

  
</ul>

  </span>

Asp.net Ajax Gotchas

Today I took a foray into asp.net's Ajax controls.
Mostly it was incredibly simple, however given Microsoft's penchant for surprises, I managed to 2 surprises.
 
I'm using Ajax to pull back a fresh copy of the session variables and display them in an
    on the sidebar.
    • Generating  an Ajax partial postback clientside
      • Some web pages will advocate __doPostBack('UpdatePanel1','');
        • This breaks if you have eventValidation on
        • Turn off event Validation at the risk of security is my guess?
      • Some web pages will advocate using a hidden button and using javascript to trigger it
        • This was the approach I got to function without an exception
    • Response.Write is not allowed in an Ajax partial update
      • <%= %> seems to have partially worked, but I think it's stripping my html tags

Wednesday, October 21, 2009

Compile-Time Safe DataBinding

No longer will I have to endure the possibilities that the designer's DataBinding broke when I changed the name of something. Nor will have to fret about leaving string literals to point to a property name. Linq Expressions to the rescue! It doesn't work on XAML, but appears to work for everything else.

It works like this:

dtpRequestDate.BindNullableValue(bsTicket, Member.Name<ModelTicket>(ticket => ticket.AddedDate), false);

cmbRequestType.BindNullableSelectedValue(bsTicket,
Member.Name<ModelTicket>(ticket => ticket.RequestTypeId));

Here's the source:

public static class Member

    {

        
private static string GetMemberName(Expression expression)

        {

            
switch (expression.NodeType)

            {

                
case ExpressionType.MemberAccess:

                    
var memberExpression = (MemberExpression)expression;

                    
var supername = GetMemberName(memberExpression.Expression);



                    
if (String.IsNullOrEmpty(supername))

                        
return memberExpression.Member.Name;



                    
return String.Concat(supername, '.', memberExpression.Member.Name);



                
case ExpressionType.Call:

                    
var callExpression = (MethodCallExpression)expression;

                    
return callExpression.Method.Name;



                
case ExpressionType.Convert:

                    
var unaryExpression = (UnaryExpression)expression;

                    
return GetMemberName(unaryExpression.Operand);



                
case ExpressionType.Parameter:

                    
return String.Empty;



                
default:

                    
throw new ArgumentException("The expression is not a member access or method call expression");

            }

        }



        
public static string Name<T>(Expression<Func<T, object>> expression)

        {

            
return GetMemberName(expression.Body);

        }



        
public static string Name<T>(Expression<Action<T>> expression)

        {

            
return GetMemberName(expression.Body);

        }

    }

Thanks to Oliver Hanappi via StackOverflow.com and this post

Nullable ComboBox.SelectedValue

Here's what I hacked out of the nullable DateTimePicker to work for the SelectedValue property of a ComboBox



        /// <summary>
        /// From BReusable
        /// </summary>
        /// <param name="comboBox"></param>
        /// <param name="dataSource"></param>
        /// <param name="valueMember"></param>

        /// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>

        public static void BindNullableSelectedValue(this ComboBox comboBox, BindingSource dataSource, String valueMember)

        {

            
var binding = new Binding(Member.Name<ComboBox>(item=>item.SelectedValue), dataSource, valueMember, true);



            
//OBJECT PROPERTY --> CONTROL VALUE

            binding.Format += ((sender, e) =>

            {

                
Binding b = sender as Binding;



                
if (b != null)

                {

                    
var  cBox = (binding.Control as ComboBox);

                    
if (cBox != null)

                    {

                        
if (e.Value == null)

                        {



                            cBox.SelectedItem=
null;



                        }


                    }



                }

            });

            
// CONTROL VALUE --> OBJECT PROPERTY

            binding.Parse += ((sender, e) =>

            {

                
// e.value is the formatted value coming from the control.
                // we change it to be the value we want to stuff in the object.

                var b = sender as Binding;



                
if (b != null)

                {

                    
var cBox = (b.Control as ComboBox);

                    
if (cBox != null)

                    {

                        e.Value = cBox.SelectedItem !=
null ? cBox.SelectedValue : null;

                    }

                }

            });

            comboBox.DataBindings.Add(binding);



        }




- Formatted via Jeff Atwood's - ModernText Visual Studio Macro

nullable DateTimePicker databinding

Code or special controls to allow a DateTimePicker to accept a nullable value are all over the place. Here's the one I'm using that is working well so far.

/// <summary>

        /// From BReusable

        /// </summary>

        /// <param name="dateTimePicker"></param>

        /// <param name="dataSource"></param>

        /// <param name="valueMember"></param>

        /// <param name="showCheckBox"></param>

        /// <remarks>With help from Dan Hanan </remarks>

        public static void BindNullableValue(this DateTimePicker dateTimePicker, BindingSource dataSource, String valueMember,bool showCheckBox)

        {

            var binding = new Binding("Value", dataSource, valueMember, true);



            //OBJECT PROPERTY --> CONTROL VALUE

            binding.Format += ((sender, e) =>

                                   {

                                       Binding b = sender as Binding;

                

                                       if (b != null)

                                       {

                                           DateTimePicker dtp = (binding.Control as DateTimePicker);

                                           if (dtp != null)

                                           {

                                               if (e.Value == null)

                                               {



                                                   dtp.ShowCheckBox = showCheckBox;

                                                   dtp.Checked = false;



                                           // have to set e.Value to SOMETHING, since it's coming in as NULL
                                           // if i set to DateTime.Today, and that's DIFFERENT than the control's current
                                           // value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
                                           // the trick - set e.Value to whatever value the control currently has. 
                                           // This does NOT cause a CHANGE, and the checkbox stays OFF.



                                                   e.Value = dtp.Value;



                                               }

                                               else

                                               {

                                                   dtp.ShowCheckBox = showCheckBox;

                                                   dtp.Checked = true;

                                           // leave e.Value unchanged - it's not null, so the DTP is fine with it.

                                               }



                                           }



                                       }

                                   });

            // CONTROL VALUE --> OBJECT PROPERTY

            binding.Parse += ((sender, e) =>

                                  {

                                      // e.value is the formatted value coming from the control. 

                                      // we change it to be the value we want to stuff in the object.

                                      var b = sender as Binding;



                                      if (b != null)

                                      {

                                          var dtp = (b.Control as DateTimePicker);

                                          if (dtp != null)

                                          {

                                              if (dtp.Checked == false)

                                              {

                                                  dtp.ShowCheckBox = showCheckBox;

                                                  dtp.Checked = false;

                                                //used to cast null to dateTime?

                                                  e.Value = null;

                                              }

                                              else

                                              {

                                                  DateTime val = Convert.ToDateTime(e.Value);

                                                  e.Value = val;

                                              }

                                          }

                                      }

                                  });

            dateTimePicker.DataBindings.Add(binding);



        }