every developer knows the listview provided by .net compact framework most of the time will not serve the purpose consider if we want a list view some thing like native inbox mail list the generic .netcf tool box does not provide any such options in such cases we can take over the paint method and draw our own items.below is the implemention of an owner-drawn ListView i came across some chinese site it worked.
//This is the basic custom list view control
using System;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using System.Data;
using System.Reflection;
using System.Drawing.Imaging;
namespace SmartUI {
enum MailIcon {
unopened,
opened
}
/// <summary>
/// simple MailItem class for each ListView item.
/// </summary>
class MailItem {
public MailIcon icon;
public string sender;
public string subject;
public MailItem(MailIcon Icon, string Sender, string Subject)
{
this.icon = Icon;
this.sender = Sender;
this.subject = Subject;
}
}
/// <summary>
/// Provide a line listview
/// </summary>
class MyListView : OwnerDrawnList {
constint Column1Left = 5;
const int Column2Left = 25;
public MyListView() {
// We need a total of 5 rows, so the height is 180/5=36
Graphics g = this.CreateGraphics();
Font font = new Font(this.Font.Name, 10, FontStyle.Bold);
// Calc line height to be height of letter A plus 10%
int fontHeight = (int)(g.MeasureString("A", font).Height*1.1);
this.ItemHeight = fontHeight*2;
g.Dispose();
}
protected override void OnKeyDown(KeyEventArgs e) {
switch(e.KeyCode) {
case Keys.Return:
MessageBox.Show("You selected item " + this.SelectedIndex.ToString(),
"Item selected",
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
break;
}
base.OnKeyDown(e);
}
protected override void OnPaint(PaintEventArgs e) {
// Declare vars
Font font;
Color fontColor;
string bmpName;
Graphics gOffScreen = Graphics.FromImage(this.OffScreen);
gOffScreen.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
int itemTop = 0;
for(int n = this.VScrollBar.Value; n <= this.VScrollBar.Value + DrawCount; n++)
{
if(n == this.SelectedIndex) //check whether if mail item is selected if so highlight the background color
{
//paint the selected rectangle with system background color
gOffScreen.FillRectangle(new SolidBrush(SystemColors.Highlight),
0,
itemTop,
this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 0),
this.ItemHeight);
fontColor = CalcTextColor(SystemColors.Highlight);
}
else
fontColor = this.ForeColor;
gOffScreen.DrawLine(new Pen(Color.DarkGray),
1,
itemTop+this.ItemHeight,
this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 2),
itemTop+this.ItemHeight);
MailItem lvi = (MailItem)this.Items[n];//paint appropriate mail item to background
if (lvi.icon == MailIcon.unopened) {
font = new Font(this.Font.Name, 10, FontStyle.Bold);
bmpName = "SmartUI.unread.bmp";
}
else {
font = new Font(this.Font.Name, 10, FontStyle.Regular);
bmpName = "SmartUI.read.bmp";
}
Bitmap bmp = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream(bmpName)); //make sure to give correct path else it may crash here
// To draw a transparent image, we need to set the transparent
ImageAttributes ia = new ImageAttributes();
ia.SetColorKey(Color.Red, Color.Red);
// Set the image rectangle
Rectangle imgRect = new Rectangle(Column1Left, itemTop+3, bmp.Width, bmp.Height);
// Draw the image
gOffScreen.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
// Draw the mail sender
gOffScreen.DrawString(lvi.sender, font, new SolidBrush(fontColor), Column2Left, itemTop);
// Draw the mail subject
gOffScreen.DrawString(lvi.subject, font, new SolidBrush(fontColor), Column2Left, itemTop + (ItemHeight/2));
font.Dispose();
bmp.Dispose();
itemTop += this.ItemHeight;
}
e.Graphics.DrawImage(this.OffScreen, 0, 0);
gOffScreen.Dispose();
}
// Draws the external border around the control.
protected override void OnPaintBackground(PaintEventArgs e) {
// e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
}
}
class OwnerDrawnList : Control {
int scrollWidth;
int itemHeight = -1;
int selectedIndex = -1;
Bitmap offScreen;
VScrollBar vs;
ArrayList items;
public OwnerDrawnList() {
this.vs = new VScrollBar();
scrollWidth = this.vs.Width;
this.vs.Parent = this;
this.vs.Visible = false;
this.vs.SmallChange = 1;
this.vs.ValueChanged += new EventHandler(this.ScrollValueChanged);
// Items to draw
this.items = new ArrayList();
}
/// <summary>
///
/// </summary>
public ArrayList Items {
get { return this.items;}
}
protected Bitmap OffScreen {
get {return this.offScreen;}
}
protected VScrollBar VScrollBar {
get {return this.vs;}
}
public event EventHandler SelectedIndexChanged;
// Raise the SelectedIndexChanged event
protected virtual void OnSelectedIndexChanged(EventArgs e) {
if(this.SelectedIndexChanged != null)
this.SelectedIndexChanged(this, e);
}
public int SelectedIndex {
get {return this.selectedIndex;}
set {
this.selectedIndex = value;
if (this.SelectedIndexChanged != null)
this.SelectedIndexChanged(this, EventArgs.Empty);
}
}
protected void ScrollValueChanged(object o, EventArgs e) {
this.Refresh();
}
protected virtual int ItemHeight {
get {return this.itemHeight;}
set {this.itemHeight = value;}
}
// If the requested index is before the first visible index then set the
// first item to be the requested index. If it is after the last visible
// index, then set the last visible index to be the requested index.
public void EnsureVisible(int index) {
if(index < this.vs.Value) {
this.vs.Value = index;
this.Refresh();
}
else if(index >= this.vs.Value + this.DrawCount) {
this.vs.Value = index - this.DrawCount + 1;
this.Refresh();
}
}
//on key press event
protected override void OnKeyDown(KeyEventArgs e) {
switch(e.KeyCode) {
case Keys.Down:
if(this.SelectedIndex < this.vs.Maximum) {
EnsureVisible(++this.SelectedIndex);
this.Refresh();
}
break;
case Keys.Up:
if(this.SelectedIndex > this.vs.Minimum) {
EnsureVisible(--this.SelectedIndex);
this.Refresh();
}
break;
}
base.OnKeyDown(e);
}
protected int DrawCount {
get {
if(this.vs.Value + this.vs.LargeChange > this.vs.Maximum)
return this.vs.Maximum - this.vs.Value + 1;
else
return this.vs.LargeChange;
}
}
protected override void OnResize(EventArgs e) {
int viewableItemCount = this.ClientSize.Height / this.ItemHeight;
this.vs.Bounds = new Rectangle(this.ClientSize.Width - scrollWidth,
0,
scrollWidth,
this.ClientSize.Height);
if(this.items.Count > viewableItemCount) {
this.vs.Visible = true;
this.vs.LargeChange = viewableItemCount;
this.offScreen = new Bitmap(this.ClientSize.Width - scrollWidth, this.ClientSize.Height);
}
else {
this.vs.Visible = false;
this.vs.LargeChange = this.items.Count;
this.offScreen = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
}
this.vs.Maximum = this.items.Count - 1;
}
protected Color CalcTextColor(Color backgroundColor) {
if(backgroundColor.Equals(Color.Empty))
return Color.Black;
int sum = backgroundColor.R + backgroundColor.G + backgroundColor.B;
if(sum > 256)
return Color.Black;
else
return Color.White;
}
}
}
//Call below code from any window form
public CustomListView()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
olv = new MyListView();
olv.Parent = this;
// Set the bounds of the listview.
olv.Bounds = new Rectangle(0,0, this.ClientSize.Width, this.ClientSize.Height);
// Add data items to listview
for (int i=0; i<10; i++) {
olv.Items.Add(new MailItem(MailIcon.unopened, "Ceveni Com", "re: Custom ListView"));
olv.Items.Add(new MailItem(MailIcon.opened, "James Bond", "Custom ListView"));
}
olv.SelectedIndex = 0;
olv.EnsureVisible(olv.SelectedIndex);
}
if there is any problem in the below code or if there is still shortest method of doing it or any free third party control readily available share with us.