TheSwamp

Code Red => .NET => Topic started by: Keith™ on January 30, 2009, 04:20:00 PM

Title: OwnerDraw ListView effectively
Post by: Keith™ on January 30, 2009, 04:20:00 PM
I have built a widget that uses a listview, textbox, combobox and labels. This widget is essentially a listview on steroids. The first column when double clicked allows editing of the contents of the selected item, the second column when double clicked allows the user to select an item from a dropdown list (combobox).

The problems I have to overcome are:

ListView only allows a single font to be specified for the entire widget
Each column can only have one text alignment

I need to have right and left aligned text in the first column and bold, center aligned text in the second.

I have set OwnerDraw to true and overridden the functions to draw the subitems and columnheaders, but the resulting text is pretty bad because I have to use Graphics.DrawString to emulate a bold font. Surely there is a better way.

I'd appreciate any insight into resolving this.
Title: Re: OwnerDraw ListView effectively
Post by: MickD on January 30, 2009, 04:54:33 PM
The only thing I can think of is to create your own listview control where you have the ability to set each individual column as you wish.
The problem with this (and the reason why it won't let you change individual columns) is you will lose the 'dynamic' ability to create a listview based on just the data source, you'll need to know exactly how many columns you need and then set each one how you like.

Basically what you have done but wrap it as a custom control.
hth.
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on January 30, 2009, 09:40:26 PM
The widget is actually a custom control. I have to use exact layout 5 times in the program with different headers, data and captions, so I made custom properties of the object. I could make it from more base objects, but I am not sure I want to write all of the code required to make that happen ...

I was hoping for some overrides that would make it easier to manipulate.

I can see I have some more research to do.
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on January 31, 2009, 03:43:21 AM
The only thing I can think of is to create your own listview control where you have the ability to set each individual column as you wish.

The DataGridView in the piccy took me about
10 minutes from start to finish (using a class
for the datasource with databinding).

Title: Re: OwnerDraw ListView effectively
Post by: MickD on January 31, 2009, 06:30:24 AM
Keith's question was whether he can change the column title attributes (alignment) in the list view control in an easier fashion to suit his application, you haven't demonstrated how this is possible Tony.
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on January 31, 2009, 10:13:51 AM
Well, after several hours of reading, I realized I could assign a new font to any cell, but I had to create the font and all of its attributes programmatically and assign it to the listview sub item.

The problem I have now is that the item showing "Total:" will not right align, even after forcing it to right align and redrawing it explicitly.

If I move the code to the DrawSubItem instead of the DrawItem, "Total:" is drawn correctly, but the item in the next column is also right justified instead of centered.


Title: Re: OwnerDraw ListView effectively
Post by: TonyT on January 31, 2009, 03:40:29 PM
Keith's question was whether he can change the column title attributes (alignment) in the list view control in an easier fashion to suit his application, you haven't demonstrated how this is possible Tony.

No, of course not.

I merely demonstrated how to achieve the ultimate
objective quckly and easily, using the right tool for
the job.
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on January 31, 2009, 04:00:19 PM
Actually, the problem is prevalent in the DataGridView as well. It seems as though you don't understand the dilemna.

I have 2 columns in a ListView, as shown in the previous examples I have provided, I suppose I could have used a simple ListBox, but that provides less configurability than the ListView.

A listview has ColumnHeaders as a sub-object of the listview control. These ColumnHeaders dictate the justification of all text in that specific column, except that column 0 can only have left justification. Subsequent ColumnHeaders allow you to align text to left, center or right. As seen in my second example, the first column (column 0) is left justified and the second column (column 1) is center. This is exactly how I want it to show with the exception of one tiny thing. I want the last item in column 0 to show "Total:" right justified.

All is not lost, because I can simply use OwnerDraw and draw the text where I want it .. right? .. except when I OwnerDraw "Total:" as right justified, Column 1 in that row is also right justified. So I thought since DrawText isn't working how I would expect for the DrawSubItem event, I would just use DrawGraphic and pass it the text values. Except the contant repainting of the control while moving the mouse over it is too much, and I end up with phantom entities.

I am not giving up on this, because I know it is possible ... heck if I can do it in a VBA ListView, why the heck doesn't it work in .NET?

Oh well ... I am going to try something else that I have not yet tried.
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on January 31, 2009, 09:44:50 PM
Actually, the problem is prevalent in the DataGridView as well. It seems as though you don't understand the dilemna.

Actually, it seems as though you don't understand the DataGridView very well.

I have absolutely no problem customizing any aspect of the appearance of
individual columns, individual rows, or even specific cells in a DataGridView,
without having to handle paint events.

Title: Re: OwnerDraw ListView effectively
Post by: Kerry on January 31, 2009, 11:13:11 PM
I don't have time to play, but these seem relevant ..

Cell Styles in the Windows Forms DataGridView Control
http://msdn.microsoft.com/en-us/library/1yef90x0.aspx

DataGridViewCell..::.Style Property
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcell.style.aspx

added:
DataGridViewCellStyle Properties
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcellstyle_properties.aspx


 .... but perhaps I don't understand the problem correctly ..  :|
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on February 01, 2009, 12:00:23 AM
Well, the issue is resolved .. strangely enough, whenever the DrawSubItem event is fired, it is apparently fired recursively for each column in the ListView.

Lets imagine that you have a ListView with 3 columns and you want to OwnerDraw only one item in the first column. The event DrawSubItem is sent the ListSubItem object. This corresponds to the FIRST column of data ONLY. i.e.

Lets say the object is "column" and the data in column 0 is "dog", column 1 is "pit bull" and column 2 is "bruno"

When column 0 is drawn, column.Item.Text = "dog" when column 1 is drawn column.Item.Text = "dog" and when column 2 is drawn, column.Item.Text = "bruno".

So, you look at the rest of the stuff ... and it shows correctly ... so, I simply had to assign a "tag" to each item and subitem ...

Now column.Item.Tag is different ... while column.Item.Text is the same ...

Strange how people build some widgets
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 01, 2009, 12:40:57 AM
Thank you :roll:

I don't have time to play, but these seem relevant ..

Cell Styles in the Windows Forms DataGridView Control
http://msdn.microsoft.com/en-us/library/1yef90x0.aspx

DataGridViewCell..::.Style Property
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcell.style.aspx

added:
DataGridViewCellStyle Properties
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcellstyle_properties.aspx


 .... but perhaps I don't understand the problem correctly ..  :|
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 01, 2009, 08:58:50 PM
And for the curious who would also prefer
to use the right tool for the job:

Code: [Select]

   // Code excerpt from DxfDataView control that shows how
   // to alter the display style of certain cells without having to
   // explicitly assign cell styles to individual cells (which is not
   // recommended in cases where there can be a large number
   // of cells).
 
   // In this case, only cells in the 'Value' column, whose
   // values represent non-null ObjectIds are affected:

   // the handler for the CellPainting event, on a stock DataGridView:

   void grid_CellPainting( object sender, DataGridViewCellPaintingEventArgs e )
   {
      DataGridViewTextBoxCell cell = GetHyperLinkCell( e.RowIndex, e.ColumnIndex );
      if( cell != null )
      {
         // modify the effective font for the cell, to use bold text:
         e.CellStyle.Font = new Font( GetEffectiveCellFont( cell ), FontStyle.Bold );

         // Set the cell's foreground color to Blue:
         e.CellStyle.ForeColor = Color.Blue;

         // Tell the cell to paint itself using the modified cell style:
         e.Paint( e.CellBounds, DataGridViewPaintParts.All );

         e.Handled = true;
      }
   }

   // Return the cell at the specified row/column index, if it's
   // content should behave like a hyperlink (e.g., an ObjectId),
   // using the bound data:

   private DataGridViewTextBoxCell GetHyperLinkCell( int rowIndex, int colIndex )
   {
      if( grid.Columns[colIndex] == colValue && rowIndex > 0 )
      {
         DataGridViewRow row = grid.Rows[rowIndex];
         DataGridViewTextBoxCell cell = row.Cells[colIndex] as DataGridViewTextBoxCell;
         DxfRecord rec = row.DataBoundItem as DxfRecord;
         if( cell != null && rec != null && rec.TypedValue.Value is ObjectId )
         {
            ObjectId id = (ObjectId) rec.TypedValue.Value;
            if( !id.IsNull && rec.Code != -1 )
               return cell;
         }
      }
      return null;
   }

   // Get the font used to draw the text in a given cell:

   static Font GetEffectiveCellFont( DataGridViewCell cell )
   {
      return cell.Style.Font
         ?? cell.DataGridView.Columns[cell.ColumnIndex].CellTemplate.Style.Font
         ?? cell.DataGridView.DefaultCellStyle.Font
         ?? cell.DataGridView.Font;
   }


I don't have time to play, but these seem relevant ..

Cell Styles in the Windows Forms DataGridView Control
http://msdn.microsoft.com/en-us/library/1yef90x0.aspx

DataGridViewCell..::.Style Property
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcell.style.aspx

added:
DataGridViewCellStyle Properties
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcellstyle_properties.aspx


 .... but perhaps I don't understand the problem correctly ..  :|
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 01, 2009, 09:43:06 PM

 .... but perhaps I don't understand the problem correctly ..  :|


Do you mean the problem that really isn't a problem in
the first place? or the other problem that serves to make
it a problem?

Most experienced in UI design do not design UIs that
act like data printed on paper hardcopy. In other words,
they don't tack summary data onto the end of scrolling
rows of the data it summarizes.

Summary data generally appears below the scrollable
data it summarizes, and is fixed.

Strange how some people build widgets, eh ?  :lol:
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on February 01, 2009, 11:19:30 PM
I get paid too well to do EXACTLY what the client wants, I don't get paid to re-invent the wheel.
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 01, 2009, 11:40:07 PM
I get paid too well to do EXACTLY what the client wants, I don't get paid to re-invent the wheel.

You mean that someone is actually paying you for that  ? ??
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 01, 2009, 11:58:47 PM

Well, after several hours of reading, I realized I could assign a new font to any cell....


Out of curiosity, do you invoice the customer for that ummmm 'research' time ?
Title: Re: OwnerDraw ListView effectively
Post by: MickD on February 02, 2009, 12:34:53 AM
Things a bit quiet down your way Tony? :laugh:
Title: Re: OwnerDraw ListView effectively
Post by: kdub_nz on February 02, 2009, 01:24:55 AM
Well, the issue is resolved ..   

Keith,
I'd be interested in seeing the code/solution that resolved your problem. How about posting something to show us ?


.......
Lets say the object is "column" and the data in column 0 is "dog", column 1 is "pit bull" and column 2 is "bruno"

When column 0 is drawn, column.Item.Text = "dog" when column 1 is drawn column.Item.Text = "dog" and when column 2 is drawn, column.Item.Text = "bruno".

......

Are you sure this is correct ... Im having trouble understanding what you mean ..

Regards
Kerry @ work.
Title: Re: OwnerDraw ListView effectively
Post by: TonyT on February 02, 2009, 02:15:20 AM
Things a bit quiet down your way Tony? :laugh:

No, at the time there was a superbowl party underway here,
so I was a little juiced and looking for a fight.  :lol:
Title: Re: OwnerDraw ListView effectively
Post by: Keith™ on February 02, 2009, 02:31:26 AM
I get paid too well to do EXACTLY what the client wants, I don't get paid to re-invent the wheel.

You mean that someone is actually paying you for that  ? ??

Why ... are you jealous?


Well, after several hours of reading, I realized I could assign a new font to any cell....


Out of curiosity, do you invoice the customer for that ummmm 'research' time ?

Fixed quote bid .. my time is mine they are purchasing deliverables only, based upon a pretty complex RFQ.

What is your problem anyway? If you don't have anything constructive to add, why bother?

Keith,
I'd be interested in seeing the code/solution that resolved your problem. How about posting something to show us ?

Well, I'll see if I can get some excerpts of code to show .. I have to be pretty careful since this is a military project.
Title: Re: OwnerDraw ListView effectively
Post by: MickD on February 02, 2009, 04:58:51 AM
Things a bit quiet down your way Tony? :laugh:

No, at the time there was a superbowl party underway here,
so I was a little juiced and looking for a fight.  :lol:

he he he... now we're talkin'. nice to see a lighter side of you Tony!
cheers,
Mick.

P.S. glad to hear the Steelers won! (being a steel guy and all). a mate of mine is over there with his wife from Pittsburgh so I'd imagine they're having a good time.