Quantcast
Channel: Mark Rideout's Blog
Viewing all 27 articles
Browse latest View live

Welcome

$
0
0

Well, this is my first blog post. I really don't know what to say or what to write about, so first I'll give a little background about myself and work.

I first was introduced to Microsoft in 1995 where I worked in an IT group developing client-server software using VB4. I later joined Microsoft full time in 1997 in another IT group as a dev lead. I worked on client-server, three-tiered and web apps developing in VB4 through VB6; MFC and C++; HTML/XML/DHTML. I went through the original "shift" from client-server to web apps. I continued in the IT group till 2001 when I decided to make a career change by becoming a documentation writer for the .NET Client/Windows Forms team working on the 1.0\1.1 release. I later changed careers one more time in 2003 and became a Program Manager (PM) for the .NET Client/Windows Forms team working on the 2.0 release. As a PM I developed some of the new features to the TreeView and ListView controls. The main feature that I worked on is the new DataGridView control. Now because of when I started as a PM part of the DataGridView control was already designed by Mark Boulter, so I took what he had and for two more years worked to finish the DataGridView design. Since I've seen the original "shift", I'm excited about the change back to the smart client with technologies like Windows Forms and Windows Presentation Framework.

Any way, that is my work background. Personally, I grew up in Missouri and I'm married with no kids (EDIT: now 1 kid), but one dog!

My thoughts for this blog are to talk about the new DataGridView control and cool ways to customize it. Let me know if you have done some cool DGV customization or you are trying to. Also let me know if there is something else you want to know about!

-mark


Customizing the DataGridView to support expanding/collapsing (ala TreeGridView)

$
0
0

One of the first things that I wanted to customize with the DataGridView is to make it support hierarchical data

If you read my first blog post you'll find out that I'm not a developer (anymore). Even though I'm not a developer I still like to take features and customize them to do something really cool. As far as the DataGridView goes, customizing it to support hierarchical data is a much larger task since the structure of the DGV doesn't lend itself to having different column sets, so, I decided I'd settled for a tree like structure.

Think of a TreeView combined with a ListView and that is basically what I wanted to go with.

NOTE: This code is not supported by Microsoft and is provided "as-is". This code it not meant to show "best practices", but just showing a concept.

NOTE: This control is written to require Visual Styles to be enabled on your computer. You'll need to modify it if you want to run the TreeGridView without visual styles.

Code: http://www.windowsforms.net/blogs/markrideout/treegridview.zip

Here is a picture:

Anyway. The basic part of creating a DataGridView that can expand and collapse is to dynamically add and remove rows. That was the easy part. To make this really usable and extendable, I decided to add a lot code and make this easier to use. Here are some details:

Design

I wanted to ensure that the design of the TreeGridView supported normal TreeView type properties and features, so creating necessary classes to create the “tree view” experience wa necessary (see object model for more details).

Custom Painting– Painting an image in a cell is easy, but ensuring that the text from the DataGridViewTextBoxCell didn’t overlap the image took a bit of work. Using the Padding feature of the DataGridViewCellStyle, I add padding to the left side of the cell to account for the text and the indentation. This padding affects the painting and behavior of the text box cell, so editing a text cell correctly positions the editing control.

Siting/Unsiting a node– Since I don’t want to set padding and styling except when a node is actually displayed. When the node is displayed or in the grid, it is sited. When the node is sited I set all the necessary properties.

Unbound– Since expanding and collapsing is based upon dynamically adding and removing rows from the grid, I decided that unbound mode would be the best way to go with this. I’ve hidden the “databinding” properties and the virtual mode property since this doesn’t support those features.

Edit Mode– One thing that I had to deal with is that double-clicking a cell enters edit mode. This double-click occurs regardless of the padding, so double-click on the +\- symbol causes the control to enter edit mode. Edit also enters if you single click on a cell that already has focus. So, to deal with this I turn edit mode to be enabled only through programmatic means. I have code to handle the F2 key to enter edit mode. There are other ways to solve this, but I went with the F2 approach.

Object model structure

TreeGridNode - Just like a tree view, I wanted to have the concept of a node. I made the nodes class derive from a DataGridViewRow since a node in the list is the same as a row, just with a bit more info.

Here are some properties:

Nodes– Again, like the treeview, a node has children, so there is a Nodes property that returns child nodes. One of the challenges in coding this is to know when a node is actually a row or when it is just a node. A node is a row when it is in the grid, otherwise it is just a node.

IsSited– A node is “sited” when it is contained in the grid as a row. The Sited property is true in this case. There are a set of protected virtual methods on the TreeGridView class (SiteNode and UnSiteNode).

ImageIndex– Image index for the node’s image. Only used when an ImageList is associated with the TreeGridView.

Image– Image associated with the node. Sets or gets the image. When an ImageList is associated with the TreeGridView and an ImageIndex is set then this returns an image from the ImageList. You can set the Image property to an image if you aren’t using an ImageList.

Cells– Returns the cells for the given node. This wasn’t easy to do since accessing the cells for a node (or row) when the node isn’t sited. Using the DataGridView’s CreateCells method I can get the correct cells collection when the node isn’t in the grid.

TreeGridCell/Column– This is a special DataGridView cell that derives from the DataGridViewTextBoxCell. The main thing that this custom cell class does is to customize the cell drawing to make it look like a tree node. That means that it draws the node’s image and the +/- icons and the tree lines. The custom cell also is where a node detects when you click the mouse to expand or collapse a node. NOTE: A lot more work can be done to correctly detect that the mouse is directly over the +/- image. Right now I’m not doing that.

TreeGridView– This class derives from the DataGridView control. Many things are done in this class. Nodes are sited/unsited in the grid as actual rows. Somce DataGridView Properties are hidden since they do not apply.

Here are some properties:

VirtualNodes– One of the common things done with a normal TreeView is to dynamically add child nodes when the user is expanding the parent. With the normal TreeView usres add temp child nodes to get the + sign and support expanding, then remove the temp node later. With the VirtualNodes property, the TreeGridView always displays a + sign next to a node, even if the node doesn’t have any children. Then, by handling the Expanding event you can dynamically add child nodes.

ImageList– ImageList associated with the TreeGridView

Nodes– Identifies the root nodes.

ShowLines– Determines if the TreeGridView shows lines between nodes.

CurrentNode– Identifies the node that has focus.

Here are some events:

Expanding– Again, like the treeview, this event occurs before a node is starting to expand. You can add nodes in this event to fill in more details of a child node collection. When the VirtualNodes property is true, the TreeGridView will display the node with a + sign next to it even when it doesn’t have any children. Handling the Expanding event is where you would dynamically add new child nodes.

Expanded– After a node is expanded.

Collapsing– Before a node is being collapsed

Collapsed– After a node has been collapsed.

I’ve included a simple test app that creates a news group reader looking list that supports expanding and collapsing.

Let me know what you think and how you've used this in your project!

-mark

DataGridView mouse scrolling button with IBM/UltraNav driver

$
0
0

As part of my work I use an IBM Thinkpad laptop a lot (T40 model) and one thing that has bugged me a lot is that the mouse wheel button on the laptop keyboard (center button) doesn't work with the DataGridView. Below is the story of my investigation and how I got this to work, including the code necessary for you to get this to work.

After a little investigation I found that the UltraNav mouse wheel didn't work with many of the Windows Forms controls which use scroll bar controls vs. using the scroll bar window style. This means that controls which use the AutoScroll feature work with the UltraNav mouse wheel, but controls that have a horizontal and/or vertical scroll bar as a child control do not work. Well, I for one wanted to find out how I could get it to work for the DataGridView, so I dug deeper in my investigation and into Win32.

The first thing I did was to take a Form with AutoScroll set to true (showing scrollbars) and set a breakpoint on the WM_VSCROLL/WM_HSCROLL windows messages in the WndProc. Sure enough, using the UltraNav mouse wheel the scroll messages are sent. This is different than a normal mouse wheel whereby a WM_MOUSEWHEEL message is sent. So I knew that the UltraNav mouse wheel system was doing things a bit different. Looking up WM_VSCROLL\WM_HSCROLL messages in MSDN says that these messages are sent by the scrollbars to its parent. When I use the UltraNav mouse wheel on a control that doesn't use AutoScroll the scroll messages are not sent. So I had a hunch that the UltraNav attempts to detect if the window has scroll bars or not to know if it sends the scroll messages. With this, I investigated the difference between a scrollbar in Outlook vs. a Windows Forms scroll bar.

Using Spy++ on the Outlook inbox view (where the UltraNav mouse wheel does work) shows me that Outlook uses a separate scrollbar control (vs. window style). Spy++ told me that there wasn't anything special about that scroll bar either. I compared the window styles and window class details between Outlook and a Windows Forms scrollbar (below screen shots - Outlook on left, Windows Forms on the right. Click on the images for a larger view).

 

The first thing I noticed was that the Outlook scrollbar had the SBS_VERT window style where the Windows Forms scroll bar has 00000001 -- what's going on here? I looked at the scrollbar code and saw that we do set the SBS_VERT window style, but Spy++ doesn't show it. I cracked the Windows.h file included in the platform SDK and noticed that SBS_VERT equals 00000001. Why does Spy++ show it as SBS_VERT for the Outlook scrollbar but as 00000001 for the Windows Forms scrollbar? I chewed on this a bit and came to a conclusion -- Spy++ only knows that 00000001 is SBS_VERT based upon the window class of Scrollbar and the Windows Forms scrollbar class name is a munged class name to make the class name unique. I found out that Windows Forms does this because we need to modify details of that window class and we can't just modify the scrollbar window class or else all scrollbars in the system would be modified (thanks Brian for this info!). So I decided that if Spy++ doesn't think a Windows Forms scrollbar is a scrollbar (enough to show SBS_VERT) then maybe UltraNav doesn't detect this as well. Based upon my thinking that UltraNav sends the scroll messages when it detects a scroll bar I thought that this is where the breakdown is occurring.

So my thinking was that if I create a native scroll bar window as a child of the DataGridView UltraNav would send the WM_VSCROLL/WM_HSCROLL windows messages. Off to Win32 land a bit more. Using the NativeWindow class, I constructed a native scroll bar window making use of some p/invoke calls (Click here for the native scroll bar code)

Ok- so I tested this out by creating a custom DataGridView class and wrote code that creates the native scroll bar window as a child of the DataGridView, and sure enough UltraNav started to send the WM_VSCROLL/WM_HSCROLL windows messages (even though I only create a native vertical scroll bar). Now, remember that the scroll bar messages are sent to the parent of the scroll bar, this means that the WM_VSCROLL/WM_HSCROLL windows messages are sent to the DataGridView's WndProc. Now things were almost working -- all I had to do was cause the DataGridView to scroll in response to the scroll messages.

Now, I could take the scroll bar messages and crack the message and perform the correct action, just as if the user used the normal DataGridView scroll bars, but I realized that would require a lot more code than what I wanted to do, so I thought - what if I send the scroll messages to the DataGridView scroll bars? My first try with this was to p/invoke SendMessage and just send the scroll messages to the correct (horizontal/vertical) scrollbar. This didn't work. I found out that when a scroll messages is generated by a normal scroll bar, they are generated first in the scrollbar's WndProc then they are "reflected" back to the parent. In the scrollbar WndProc the message isn't WM_VSCROLL/WM_HSCROLL, but WM_VSCROLL + WM_REFLECT and WM_HSCROLL + WM_REFLECT and they then end up in the scrollbar's parent WndProc as WM_VSCROLL/WM_HSCROLL. Well, so I thought -- why don't I just reflect the messages back to the scrollbar. And this worked! In fact, Windows Forms has a great static function on Control called ReflectMessage. 

So it's done -- using a custom native scroll bar class and a custom DataGridView, my Thinkpad UltraNav mouse scroll button works! I think I'll use this in other custom controls that I write! You can download the complete code listing here.

Anyway, hopefully this will be useful to someone else as much as it is to me! Maybe in the future we can be IBM to update UltraNav to work better with Windows Forms so a hack like this isn't necessary.

-mark

New link for TreeGridView

Media player like rating DataGridView column

$
0
0

One request that I've seen a few times is to have a column in the DataGridView display a rating like stars similar to what you would find in Media Player. I've posted this over at the MSDN forums, but I thought having it in the blog would also be good.

Basically, this column/cell (called RatingColumn/RatingCell) derives from the DataGridViewImageColumn/ImageCell. This is done obviously since I am displaying an image (this is the formatted value/type), but the cell relies on integer data (0 through 5 for each star), so I change the ValueType for the column to be of type integer.

Since an integer cannot be converted to an image by magic, I override the GetFormattedValue and convert the integer value to the proper image. I use a simple array of images so the values 0 through 5 correctly index into the array. (I ended up creating 12 images in total - 6 images that go from 0 to 5 stars highlighted and another set of images that have a hot-highlight that I use for mouse over:and .) I also default the new row to the value of 3 (for three stars). Lastly, I override the Paint method to identify the star that the mouse is over. The logic to identify which star the mouse is over is a bit conviluted, but it works.

Anyway, here is the link to the unsupported sample (in c#): http://www.windowsforms.net/blogs/markrideout/RatingCustomDGVColumn.zip

One important note --  I did not add keyboard accessibility, only mouse.

-mark

UltraNav Scroll Helper - followup

$
0
0

As a follow up to my post on getting the DataGridView and UltraNav/IBM scroll button to work, I've created a simple component that makes adding UltraNav support throughout your app easy. The code is contained in a class called UltraNavScrollHelper.

Here are two usages:

A) Use with DataGridView
public class myDGV : DataGridView
{
    private UltraNavScrollHelper scrollHelper;
    public myDGV()
    {
        scrollHelper = new UltraNavScrollHelper(this, this.HorizontalScrollBar, this.VerticalScrollBar);
    }
    protected override void Dispose(bool disposing)
    {
        this.scrollHelper.Dispose();
        base.Dispose(disposing);
    }
}

B) Use at design time with scroll bar controls

  1. Create panel
  2. drag and drop horizontal and vertical scroll bar controls in the panel
  3. drag and drop the UltraNavScrollHelper component from the toolbox
  4. Set the UltraNavScrollHelper Control property to the panel
  5. Set the UltraNavScrollHelper HorizontalScrollBar and VerticalScrollBar properties to the horizontal and vertical scroll bar controls on the panel.
  6. Run

-mark

New Whitepaper/Samples for creating custom DataGridView cell/columns

Still alive.

$
0
0

Sorry I haven't posted any new. Since March I've moved to a different group here at Microsoft and on the home front I've become a father to a baby girl! Hopefully in the next few months I'll post more about what I'm doing here at Microsoft.

 

thanks
-mark

Shortest story of the past two years

$
0
0

Yup I've not updated my blog for almost 2 years. The shortest story for the past two years is that:

  • We started a family (see previous post)
  • I changed jobs – I've been a PM on Silverlight since 2006
  • Shipped Silverlight 1.0
  • Working on Silverlight 2
  • At TechEd 2008

What a Wild time.

-mark

Ok – what about this Silverlight thing?

$
0
0

As you can see I concluded my "short story" blog post (previous post) saying that I'm at TechEd – and that is correct. I'll be at TechEd 2008 all this (June 2nd through June 6th ) week. I'll be presenting on Tuesday about Silverlight 2 so please come by and listen (3pm to 6pm EST in S210). If you are a Windows Forms (winforms) user and are interested in Silverlight – stop by also. If you have followed what DataGridView stuff – way till you see the Silverlight DataGrid. Hats off to Scott Morrison who has been driving that.

 

Moving from being a Program Manager for Windows Forms to Silverlight has really done one thing: Made me excited again about client technology! It seemed there was a point where Windows Forms was getting outdone by Ajax and html sites. Even though Windows Forms was about "smart clients" and Click Once is a really cool feature for deployment, I felt that application development strategies were slowly giving up on client apps. My involvement (read: job) with Silverlight and Silverlight 2's support for.Net programming are the two things that have me excited again about client development.

 

A few of the most geekest things that I love about Silverlight in probably the correct order:

·         there are no hWnds to worry about.

·         Displaying a rectangle doesn't involve an hWnd or me making GDI calls

·         Animation

·         Easy gradients

·         Rewriting TextBox from scratch

·         Learning way too much about text and glyphs

 

Well, I'm going to run through my slide deck one more time before my talk. I hope to be more active on my blog. I know it won't be a "blog entry a day" but more like "a blog entry every now and then"

 

-mark

Pwnd by the demo gods

$
0
0

Ok – so my TechEd presentation came and went and all I can say is that "I was pwnd by the demo gods!" Yup if something could go wrong it did. Does anyone else need a café express tee shirt "I was pwnd by the demo gods!"? I think I will wear one around for the next month.

 

I'll be doing another presentation of the first part (IMHO the best part) on Thursday 6/5 at 11:00am in the Red TLC- Windows Booth.

 

This time I've paid some extra $$ to the gods and know the low key presentation will work great. Please show up!

 

Thanks,

-mark

TechEd Session Slides

TechEd Session Building a Silverlight Application Project

$
0
0

Finally I'm positing the Silverlight 2 Beta 2 project for my TechEd "Building Rich Internet Applications in Silverlight" talk. Sorry for the week delay I took off after TechEd for my daughter's 2nd birthday party (remember I said that I'm a proud dad?)

 

Here is the link to the project zip:

http://cid-3a5ca8204ec61147.skydrive.live.com/self.aspx/Public/TechEd2008-MarkRideout.zip

 

 

Two things to note:

1)     I removed the usage of the special "isolated storage" helper class but left the class in the zip file (not included in the project but it is in the directory). The isolated storage apis are a bit simpler from Beta 1 so the helper class really isn't needed. I'll post some more details about the iso-storage apis here in a bit.

2)     To use the navigation helper for web browser history navigation you must run the page from the ASP.NET project, not from the simple HTML page. The ASP.NET project is under the TechEd08Web project folder

 

 -mark

Great accessiblity post

Links Fixed Updated

$
0
0

Sorry for the hiccup on some of the links for samples. Those have now been fixed.

-mark


Code published on my blog is Ms-PL licensed

Still alive.

$
0
0

Sorry I haven’t posted any new. Since March I’ve moved to a different group here at Microsoft and on the home front I’ve become a father to a baby girl! Hopefully in the next few months I’ll post more about what I’m doing here at Microsoft.


 

thanks
-mark

test1 title

Shortest story of the past two years

$
0
0

Yup I’ve not updated my blog for almost 2 years. The shortest story for the past two years is that:



  • We started a family (see previous post)

  • I changed jobs – I’ve been a PM on Silverlight since 2006

  • Shipped Silverlight 1.0

  • Working on Silverlight 2

  • At TechEd 2008


What a Wild time.


-mark

Ok – what about this Silverlight thing?

$
0
0

As you can see I concluded my “short story” blog post (previous post) saying that I’m at TechEd – and that is correct. I’ll be at TechEd 2008 all this (June 2nd through June 6th ) week. I’ll be presenting on Tuesday about Silverlight 2 so please come by and listen (3pm to 6pm EST in S210). If you are a Windows Forms (winforms) user and are interested in Silverlight – stop by also. If you have followed what DataGridView stuff – way till you see the Silverlight DataGrid. Hats off to Scott Morrison who has been driving that.


 


Moving from being a Program Manager for Windows Forms to Silverlight has really done one thing: Made me excited again about client technology! It seemed there was a point where Windows Forms was getting outdone by Ajax and html sites. Even though Windows Forms was about “smart clients” and Click Once is a really cool feature for deployment, I felt that application development strategies were slowly giving up on client apps. My involvement (read: job) with Silverlight and Silverlight 2’s support for.Net programming are the two things that have me excited again about client development.


 


A few of the most geekest things that I love about Silverlight in probably the correct order:


·         there are no hWnds to worry about.


·         Displaying a rectangle doesn’t involve an hWnd or me making GDI calls


·         Animation


·         Easy gradients


·         Rewriting TextBox from scratch


·         Learning way too much about text and glyphs


 


Well, I’m going to run through my slide deck one more time before my talk. I hope to be more active on my blog. I know it won’t be a “blog entry a day” but more like “a blog entry every now and then”


 

-mark
Viewing all 27 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>