Saturday, October 3, 2009

ASP.NET - The next control

As my next control, think I might see if I can create a tree table. Similar to SwingLabs Java JXTreeTable but in web form using AJAX. Allowing data to be aggregated by dimension data and also allowing the fact data to be either collated or calculated (e.g. sum, avg, min, max, etc..). Stay tuned, to see if I can pull this one off.

ASP.NET - Date Picker Server/User Control

I finally posted my first article on CodeProject.com - http://www.codeproject.com/KB/webforms/datepicker.aspx .

The article provides an example on how to develop a ASP.NET Date Picker server control, utilizing: embedded web resources, client scripts, inner properties, and globalization (date formating). It includes both source and ready to use build/demo.

This release had two main focuses. Firstly, due to being Australian (d/MM/yyyy) I wanted the control to be compatiable with different culture date formats through the use of globalization. Secondly, the control needed to provide a high level style/appearance control by utilizing the inner property persistence mode.

Saturday, September 12, 2009

.NET: Using reflection to invoke TableAdapter methods within an DataSet XSD Template

Wow! So much making up lost time... 6 months later :-)
If you can spare the overhead cost of utilising reflection, it can come in handy when wanting to make your code flexible and allow for configuration changes without having to rebuild the application. For instance, I found a handy use for reflection when wanting to create a generic function to execute methods of any TableAdapter within an DataSet XSD template. In this example, I use reflection to fill a DataTable using any TableAdapter just by referencing the table name.
//C# - Fill DataTable from XSD DataSet Template Table Adapter
public static DataTable GetDataTable(String tableName)
{
    try
    {
        //Create table instance
        Type tableType = Type.GetType("MyApplication.MyDataSet").GetNestedType(tableName + "DataTable");
        object table = Assembly.GetExecutingAssembly().CreateInstance(tableType.FullName);
        //Create adapter instance
        Type adapterType = Type.GetType("MyApplication.MyDataSetTableAdapters." + tableName + "TableAdapter");
        object adapter = Assembly.GetExecutingAssembly().CreateInstance(adapterType.FullName);
        //Invoke fill method
        MethodInfo fillMethod = adapterType.GetMethod("Fill", new Type[] { tableType });
        fillMethod.Invoke(adapter, new object[] { table });
       
        return (DataTable) table;
    }
    catch (Exception ex)
    {
        return null;
    }
}
You can also apply this same method to provide access to other defined methods; e.g. insert, delete, & update. To achieve this you need to modify the invoke method and define your parameters in an object array. In this example, I’ve created a method that takes the name of the table, name of the method to execute and an object array that contains the parameter values for the executing method.
/*** Define parameters in an object array, matching exactly the value types of the method parameters. ***/
object[] objParams = new object[] { 1, "Bob", "Jane" };
/*** Pass table name, method name (e.g. Insert) and parameter object array to function. ***/
public static void ExecuteMethod(String tableName,
String methodName, object[] objParams)
{
    try
    {
        //Create adapter instance
        Type adapterType = Type.GetType("MyApplication.MyDataSetTableAdapters." + tableName + "TableAdapter");
        object adapter = Assembly.GetExecutingAssembly().CreateInstance(adapterType.FullName);
        //Invoke insert method
        MethodInfo method = adapterType.GetMethod(methodName);
        method.Invoke(adapter, objParams);
       
    }
    catch (Exception ex)
    {
        throw new Exception("TableAdapter Method Failed!");
    }
}

Saturday, March 14, 2009

ASP.NET: Custom date picker user control without code behind.

It's been a little while since my last post. Hopefully I'll make up lost time over the next couple of days.

Today's post includes some sample code I wrote for a custom date picker user control. The control consists of a standard Asp.Net TextBox, a HTML IMG, a DIV container and some simple Javascript. Since this is only a draft, the attached source code only includes the markup source code. No code behind for custom control properties has been developed. Over the next couple of days the code will be extended to allow configuration of appearance and other functionality.

The're two main functions to the code:
  • To minimise confliction with other control's javascript functions & variable names, the user control's ID has been written to the front of all function and global variable names. For example:

    function <% Response.Write(this.ClientID); %>FindPos(obj) {

    If the control ClientID is "DatePicker1" then the following will be written at runtime:

    function DatePicker1FindPos(obj) {

  • For setting the absolute position of the calendar panel relative to the TextBox, the offset position of the TextBox was required. To find the offset position of an element using javascript, the following function was used:

    function <% Response.Write(this.ClientID); %>findPos(obj) {
    var curLeft = curTop = 0;
    if (obj.offsetParent) {
    do {
    curLeft += obj.offsetLeft;
    curTop += obj.offsetTop;
    } while (obj = obj.offsetParent);
    }
    return [curLeft, curTop];
    }
I couldn't get the code to successfully display in the blog entry. I published the code as a Google Document.

Click here to view the ASP.Net DatePicker C# markup source code.


Wednesday, February 25, 2009

.NET: [Draft] Custom control border that allows rounded corners

Today I have commenced creating additional functionality to the user control in the previous post. These additions, will allow the border width, border color, border corner style (round or square) and border corner radius to be set.

For this draft I have only written it in C#. Once this update is complete, I will also post the VB equivalent.


// Border color
private Color _borderColor = Color.Black;
public Color BorderColor
{
    get
    {
        return this._borderColor;
    }
    set
    {
        this._borderColor = value;
        this.Refresh();
    }
}
// Border width
private int _borderWidth = 1;
public int BorderWidth
{
    get
    {
        return this._borderWidth;
    }
    set
    {
        this._borderWidth = value;
        this.Refresh();
    }
}
// Radius for drawing border corner arcs.
private int _cornerRadius = 10;
public int CornerRadius
{
    get
    {
        return this._cornerRadius;
    }
    set
    {
        this._cornerRadius = value;
        this.Refresh();
    }
}
// Border style type
public enum CornerType
{
    Square = 0,
    Round = 1
}
private CornerType _cornerStyle = CornerType.Square;
public CornerType CornerStyle
{
    get
    {
        return this._cornerStyle;
    }
    set
    {
        this._cornerStyle = value;
        this.Refresh();
    }
}
// Create a path based off the control ClientRectangle property
private GraphicsPath ClientPath
{
    get
    {
        GraphicsPath path = new GraphicsPath();
        // Create path bounds from ClientRectangle - BorderWidth
        Rectangle rect = new Rectangle(this.ClientRectangle.X, this.ClientRectangle.Y,
            this.ClientRectangle.Width - this.BorderWidth, this.ClientRectangle.Height - this.BorderWidth);
       
        switch (this.CornerStyle)
        {
            case CornerType.Square:
                path.AddRectangle(rect);
                path.CloseAllFigures();
                return path;
            case CornerType.Round:
                path.AddArc(rect.Left,
                    rect.Top,
                    this.CornerRadius, this.CornerRadius, 180, 90);
                path.AddLine(rect.Left + this.CornerRadius,
                    rect.Top,
                    rect.Right - this.CornerRadius,
                    rect.Top);
                path.AddArc(rect.Right - this.CornerRadius,
                    rect.Top,
                    this.CornerRadius, this.CornerRadius, 270, 90);
                path.AddLine(rect.Right,
                    rect.Top + this.CornerRadius,
                    rect.Right,
                    rect.Bottom - this.CornerRadius);
                path.AddArc(rect.Right - this.CornerRadius,
                    rect.Bottom - this.CornerRadius,
                    this.CornerRadius, this.CornerRadius, 0, 90);
                path.AddLine(rect.Right - this.CornerRadius,
                    rect.Bottom,
                    rect.Left + this.CornerRadius,
                    rect.Bottom);
                path.AddArc(rect.Left,
                    rect.Bottom - this.CornerRadius,
                    this.CornerRadius, this.CornerRadius, 90, 90);
                path.AddLine(rect.Left,
                    rect.Bottom - this.CornerRadius,
                    rect.Left,
                    rect.Top + this.CornerRadius);
                path.CloseAllFigures();
                return path;
            default:
                path.AddRectangle(rect);
                path.CloseAllFigures();
                return path;
        }
    }
}
// Override default OnPaintBackground event.
// Enable AntiAlias smoothing mode, to smooth the border out.
protected override void  OnPaintBackground(PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.FillPath(new SolidBrush(Color.FromArgb(this.Opacity, this.BackColor)), this.ClientPath);
    e.Graphics.DrawPath(new Pen(new SolidBrush(Color.FromArgb(this.Opacity, this.BorderColor)),this.BorderWidth), this.ClientPath);
}

Tuesday, February 24, 2009

.NET: Transparent forms and controls with opacity control

Today's code demonstrates how to create transparent forms and controls with a opacity property. It involves overriding the control classes CreateParams property & OnPaintBackground event, and creating a new property called Opacity that allows an integer value that will represent the alpha value of a colour.

Just add the following code to your control class (may it be a form, label, etc).

You will be required to declare the following in your class:
  • System 
  • System.ComponentModel
  • System.Drawing 
  • System.Windows.Forms
  • System.Windows.Forms.Design


VB
Public Sub New()
    InitializeComponent()
    ' Enables support for transparent back color for inner controls
    SetStyle(ControlStyles.SupportsTransparentBackColor, True)
End Sub
' This enables transparent backgrounds for the control
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
    Get
        Dim cp As CreateParams = MyBase.CreateParams()
        cp.ExStyle = cp.ExStyle Or &H20
        Return cp
    End Get
End Property
' A property to adjust the opacity level
Private _opacity As Integer = 255
"Set opacity of control. 0 to 255")> _
Public Property Opacity() As Integer
    Get
        Return Me._opacity
    End Get
    Set(ByVal value As Integer)
        Me._opacity = value
        Me.Refresh()
    End Set
End Property
' Override default OnPaintBackground event.
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
    e.Graphics.FillRectangle(New SolidBrush( _
    Color.FromArgb(Me.Opacity, Me.BackColor)), Me.ClientRectangle)
End Sub
C#
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public UserControl1()
{
    InitializeComponent();
    // Enables support for transparent back color for inner controls.
    SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
// This enables transparent backgrounds for the control.
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x20;
        return cp;
    }
}
// A property to adjust the opacity level.
private int _opacity = 255;
[Description("Set opacity of control. 0 to 255")]
public int Opacity
{
    get
    {
        return this._opacity;
    }
    set
    {
        this._opacity = value;
        this.Refresh();
    }
}
// Override default OnPaintBackground event.
protected override void  OnPaintBackground(PaintEventArgs e)
{
    e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(this.Opacity, this.BackColor)), this.ClientRectangle);
}