Monday, July 17, 2006

.Net Cloning

Two interesting articles on cloning:

http://www.codeproject.com/csharp/cloneimpl_class.asp?forumid=13965&exp=0&select=377851&df=100&fr=21.5#xx377851xx

http://www.agiledeveloper.com/articles/cloning072002.htm

The first one uses Reflection - main advantage is you don't have to update the function if you add fields to t he class - main disadvantage is you don't have detailed control (e.g. - if a field supports ICloneable it uses the clone mehtod, but Clone does a shallow copy - what if you want to do a deep copy - or what if you want to do some custom action - like generate a new guid for a guid field? - you can add customizations but then the function is not generic and you lose the main advantage.

The main disadvantge of the second one is that you have to modify it with any changes to the fields - but it is elegant and simple and for hte problem I'm working on right now, I have a lot of custom handling for different fields, so I don't think the first one would work.

Serialization is another option, but this gives a security issue - also may be a performance issue? and I would still have to write additional code for my custom handling.

Saturday, July 15, 2006

DataGridViewButtonColumn click event

I just realized that you capture the click event for the DataGridViewButtonColumn the same way you do any other column - through the DataGridView's CellClick event - The button column does not have it's own click event! So basically what makes it a button column is not it's functionality but the picture of the button that gets drawn and the press/depress "animation." In fact none of the column types expose their own events - they all rely on capturing the DataGridViews events.

More on DataPropertyName

If a DataGridViewColumn has a null DataPropertyName the columns index will be set to 0. (if there is more than 1 column like this, then 0,1,2, etc.) - this of course messes up the indexes of your other columns too.

So if you are capturing the cellclick event and you find that e.ColumnIndex is not what you expect, it may be that you forgot to bind one of your columns (not necessarily the same one you're clicking) to a DataColumn. This is particularly likely if one of your columns if a DataGridViewButtoncolumn, or some other column that has no data behind it - so you may not have noticed it wasn't bound.

This is the same problem I was running into with the DataGridViewImageColumn - but with this problem I have no workaround becuase it seems that binding the column properly causes the image not to show up - I'll have to make a test app to confirm this.

DataPropertyName

Looking back over my old posts it seems that for the DataGridViewImageColumn, setting the DataPropertyName to the same name as the corresponding column in the DataTable causing a problem, but with the DataGridViewTextBoxColumn, you must set the DataPropertyName to the name of the corresponding DataColumn. Hmm...

DataGridViewColumn DataPropertyName

This is an important property in every DataGridViewColumn. If you are binding to a DataTable, you must set this property to the name of the column in the DataTable that you want to bind this DataGridColumn to.

For example: Open a new Windows Form project. Add a DataGridView control to the main form. Right click on the DataGridView, select edit columns, add a DataGridViewTextBoxColumn (just call it Column1).

Now put this code in the constructor:


public partial class Form1 : Form
{
private DataTable dt;
private DataSet ds;

public Form1()
{
InitializeComponent();
dt = new DataTable("mytable");
dt.Columns.Add("Name");
dt.Rows.Add(new object[]{"michelle"});
ds = new DataSet();
ds.Tables.Add(dt);
this.dataGridView1.DataSource = ds;
this.dataGridView1.DataMember = "mytable";
}
}

Run the project - two columns will show up - Column1 and Name, the one row, will be blank for Column1 and Michelle for Name. This is probably not what we want.

Now go back to the Designer View - right click on the DataGridView and select edit columns, select Column1 and set DataPropertyName to Name.

Now run it again. This time you should get one column titled Name, with one row, michelle. Much better!

Sunday, July 09, 2006

To Change current cell in DataGridView..

this.myDGV.CurrentCell = this.myDGV.Rows[0].Cells[1];

This will automatically highlight the row as well - at least if you have MultiSelect set to false and SelectionMode to FullRowSelect

Saturday, July 08, 2006

Highlight entire row in DataGridView

To highlight an entire row in the DataGridView, set the SelectionMode property to FullRowSelect.

DataGridViewImageColumn

The first problem I haad with this column type is that my image wasn't showing up - I could see the image just fine in the column editor in Design View, but when I ran my app, only a blank image (red x) showed up.

The problem turned out to be with the DataTable I was binding to. Although the DataTable did have columns corresponding to my two image columns, those columns didn't have any data. Populating them with blank strings in every row fixed the problem...

...and uncovered a bigger problem. Now I was getting a whole slew of these exceptions whenever my DataGridView was first painted:
Invalid cast from System.String to System.Drawing.Image

The problem turned out to be with the names of the DataColumns in my DataTable - the two columns corresponding to my Image Columns were called "Up" and "Down" - e.g.:


this.myDataTable.Columns.AddRange(
new DataColumn[]{
new DataColumn("Description", typeof(string)),
new DataColumn("Up", typeof(string)),
new DataColumn("Down", typeof(string)),
new DataColumn("Delete", typeof(string))});

I'm still not sure why "Up" and "Down" caused a problem - these names happened to be the same as the DataPropertyName for the corresponding DataGridViewImageColumns, so that may have been the problem. Changing these two column names to blank strings or to "1" and "2" solved the problem.

..But now I had a new problem..it seems that when you add a DataGridViewImageColumn, another blank column is automatically added next to the DataGridView. So in this case I was getting two extra columns showing up. The only way I've found around this so far is to figure out the indexes of the extra columns and set their visible property to false.

After all that, I had a nice data grid with my image columns showing up and without any exceptions or extra columns!

DataGridViewButtonColumn

I've just started experimenting with the new DataGridView control in 2.0. I've learned a couple interesting things so far while trying to create some button columns.

First, in order to display text on the DataGridViewButtonColumn you must not only set the Text property, but must also set the UseColumnTextForButtonValue to true.

You cannot load an image on to a DataGridViewButtonColumn. Instead you must use a DataGridViewImageControl and capture the cellclick event to treat it like a button.

First Post

Welcome to Everything Dot Net. The purpose of this blog is to discuss anything and everything related to Microsoft.Net.