Author Topic: OwnerDraw ListView effectively  (Read 12954 times)

0 Members and 1 Guest are viewing this topic.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
OwnerDraw ListView effectively
« 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.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

MickD

  • King Gator
  • Posts: 3638
  • (x-in)->[process]->(y-out) ... simples!
Re: OwnerDraw ListView effectively
« Reply #1 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.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: OwnerDraw ListView effectively
« Reply #2 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.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #3 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).


MickD

  • King Gator
  • Posts: 3638
  • (x-in)->[process]->(y-out) ... simples!
Re: OwnerDraw ListView effectively
« Reply #4 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.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: OwnerDraw ListView effectively
« Reply #5 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.


Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #6 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.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: OwnerDraw ListView effectively
« Reply #7 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.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #8 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.


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: OwnerDraw ListView effectively
« Reply #9 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 ..  :|
« Last Edit: January 31, 2009, 11:23:45 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: OwnerDraw ListView effectively
« Reply #10 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
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #11 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 ..  :|

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #12 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 ..  :|
« Last Edit: February 01, 2009, 11:36:37 PM by TonyT »

TonyT

  • Guest
Re: OwnerDraw ListView effectively
« Reply #13 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:

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: OwnerDraw ListView effectively
« Reply #14 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.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie