Setup Project Tutorial

This is a simple step-by-step tutorial for creating a Setup project for a windows forms application under Visual Studio 2005.

First select the solution in the Solution  Explorer.

Right click and Select Add…New Project.

Select Other Project Types | Setup and Deployment | Setup Project.

Name the project Setup. 

Select the Setup Project in the solution explorer.

Select Properties.

Set the ProductName to whatever you will want to appear in the add remove programs dialog.

Set InstallAllUsers to True. 

Set the Author and Manufacturer to appropriate values.

Return to the solution Explorer. 

Right click on Setup and select View.

Select the Application Folder and go to the property windows.

If you don’t want to include the manufacturer in the install directory remove [Manufacturer] from the DefaultLocation. 

Return to the Solution Explorer and select the Setup Project.

Right Click and select Add…| Project Output

Save All.

Return to the Solution Explorer and Select Build.

This will create a setup.exe and a setup.msi file. 

This is the minimal installation required. 

Documentation, What Documentation? Setup.

I have been having fun lately trying to use msdn and msdn2 in order to obtain useful information about the .NET Framework.

This is rather frustrating as it appears that at least 50% of the documentation has been automatically generated from the code and provides little more detail than the intellisense. I would expect examples in all non-trivial classes plus references to related attributes and interfaces. It would also be useful if links to tutorials were included.

Over the past week I have been posting about getting databinding to work in a programatically controlled manner. Most of the information to do this was found via blogs. It appears that MSDN2 has been based upon the maze in Classic Adventure.

Today I have been looking for a tutorial on how to get the Setup project to work. The UI for this in VS2005 is very counter-intuative and the defaults are not very good.

My first step was to go to msdn2 and search for “setup project tutorial”.

The first link is here. This is completely useless. It tells us nothing that you can guess from the IDE.  This article is actually part of a crystal reports installation tutorial.

What should you enter as the project name? 

After a bit more hunting around I found the following page.

Here is a list of the properties used in the installer. 

It would appear that ProductName is a rather important property to be set. This is the one used by the add/remove programs option. Other important items are the version and the Product code.

I intend to follow up on this article with a detailed tutorial on how to write a setup project.

Combobox Bug

Try the following:

Drop a comboxbox onto a windows form.

Add the following code to the forms constructor:

List _List = new List();
_List.Add(null);
_List.Add(“A”);
comboBox1.DataSource = _List;

The comboxbox drop down is not populated.

Populate the list the other way around and the list will only have 1 item.

Problems With BindingList<> part 3.

I have finally got the binding list down to a useful class plus an attribute.

This is not quite an attribute based approach but would be very useful for custom collections. 

DisplayNameAttribute is the useful meand of marking the column as being included. 

This would make a useful generic. 

My Fields string array sorts and filters the columns:

using System.Collections.Generic;
using System.ComponentModel;

namespace WindowsApplicationDataBinding
{
    public class Node
    {
        private string _Name;
        [DisplayName(“Full Name”)]
        public string Name{ get{return _Name;} set{_Name = Name;}}

        private int _Age;

        [DisplayName(“Age (years)”)]
        public int Age
        {
            get { return _Age; }
            set { _Age = value; }
        }

        public Node(string name, int age)
        {
            _Name = name;
            _Age = age;
        }
 

        // I don’t want this shown in the list

        public string Birthday { get { return “Unknown”; } }

    }
   
    public class BindingClass : BindingList<Node>, ITypedList
    {
        private string[] _Fields = new string[] {“Name”,”Age”};
       
        private PropertyDescriptorCollection _Description = null;

        #region ITypedList Members

        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            if (_Description == null)
            {               
                // The default sort is alphabetical by field name.

               PropertyDescriptorCollection Temp =
                    TypeDescriptor.GetProperties(typeof(Node)).Sort(_Fields);
                _Description = new PropertyDescriptorCollection(null);
                foreach (PropertyDescriptor pd in Temp)
                {
                    foreach(string s in _Fields)
                    {
                        if (s == pd.Name)
                        {
                            _Description.Add(pd);
                        }
                    }
                }
               
            }
            return _Description;
        }

        public string GetListName(PropertyDescriptor[] listAccessors)
        {
            return typeof(Node).Name;
        }

        #endregion
    }
}

 

Problems With BindingList<> part 2.

I have got closer to cleaning up the BindingList<> problem:

using System.Collections.Generic;
using System.ComponentModel;

namespace WindowsApplicationDataBinding
{
public class Node
{
private string _Name;
public string Name{ get{return _Name;} set{_Name = Name;}}

private int _Age;

public int Age
{
get { return _Age; }
set { _Age = value; }
}

public Node(string name, int age)
{
_Name = name;
_Age = age;
}

public string Birthday { get { return “Unknown”; } }

}

public class BindingClass : BindingList, ITypedList
{
private PropertyDescriptorCollection _Description = null;

#region ITypedList Members

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (_Description == null)
{
_Description = TypeDescriptor.GetProperties(typeof(Node)).Sort(new string[] {“Name”, “Age”});
}
return _Description;
}

public string GetListName(PropertyDescriptor[] listAccessors)
{
return typeof(Node).Name;
}

#endregion
}
}

This version allows the application to specify the sort order of the columns.

The next step is to move this into an attribute based version.

It would also be useful if the description and hidden could be set on the same attribute.

What I want is to mark node as:

[BindingDetails(Description=”First Name”,Order=1,Hidden=False)]

string Name …

Problems with BindingList<>

I am having some trouble with the BindingList<>

There does not seem to be a simple means of defining the sort order of the columns in theunderlying type.  I would have assumed that there would be some form of attribute based approach to this. 

Here is a small sample of my experiments: 

    public class Node
    {
        private string _Name;
        public string Name{ get{return _Name;} set{_Name = Name;}}

        private int _Age;

        public int Age
        {
            get { return _Age; }
            set { _Age = value; }
        }

        public Node(string name, int age)
        {
            _Name = name;
            _Age = age;
        }

    }
   
    public class BindingClass : BindingList<Node>
    {
        public BindingClass()
        {
           
        }
    }
 

… 

        private BindingClass _Data = new BindingClass();
        
        public Form1()
        {
            InitializeComponent();
            
            _Data.Add(new Node(“Tom”,50));
            _Data.Add(new Node(“Dick”, 40));
            _Data.Add(new Node(“Harry”, 30));
            dataGridView1.DataSource = _Data;
            dataGridView1.Columns[0].DataPropertyName = “Name”;
            dataGridView1.Columns[0].HeaderText = “First Name”;
            dataGridView1.Columns[1].DataPropertyName = “Age”;
            dataGridView1.Columns[1].HeaderText = “Age”;
         }

This seems to be the least code needed to define the column order, titles and names.

How to get the information required to code generate stored procedures for sql 2000

The following is the SQL required to get what is needed from a SQL Server 2000 so that a read-only DAL can be generated from a view.

SELECT obj.name AS VIEW_NAME,
       col.name AS COLUMN_NAME,
       types.name AS COL_DATATYPE,
       col.length
FROM syscolumns col
JOIN sysobjects obj ON col.id = obj.id AND obj.xtype = ‘V’
JOIN systypes types ON col.xtype = types.xtype
WHERE obj.name NOT LIKE ‘SYS%’
ORDER BY obj.name, col.colorder

DBF Creation via OLE-DB

This is a link to an article on DB Base file creation via OLE-DB.

The following is the important part:

OleDbConnection conn = new OleDbConnection(@”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:tempdbase;Extended Properties=DBASE IV;”);

OleDbCommand cmd = new OleDbCommand(“CREATE TABLE aDBaseFile (col1 Integer,col2 Double)”, conn);

conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

The following is the equivalent in VBA

Sub foo()
‘ Add a reference to c:program filescommon filessystemadomsado15.dll
Dim c As New Connection
c.ConnectionString = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:tempdbase;Extended Properties=DBASE IV;”
c.Open
c.Execute (“CREATE TABLE DBF3 (col1 Integer,col2 Double)”)
c.Close
End Sub