Tiny programs (C, C++, C#, ...)
File detail
Source code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace proj2.UserControls
{
public partial class CategoryBrowser : UserControl
{
private dbDataSet dataSet;
private dbDataSet.productCategoriesDataTable pcTable;
/// <summary>
/// StatusMessageEventHandler event parameter structure
/// </summary>
public class StatusMessageEventArgs: EventArgs
{
private string msg;
public StatusMessageEventArgs(string statusMessage)
{
msg = statusMessage;
}
public string StatusMessageText { get { return msg; } }
}
public event EventHandler ChangesMade;
/// <summary>
/// EventHandler to delegate status info messages to parent component
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void StatusMessageEventHandler (object sender, StatusMessageEventArgs e);
/// <summary>
/// Event to delegate status info messages to parent component
/// </summary>
public event StatusMessageEventHandler StatusMessageChanged;
public void AddToToolBarDropDown(ToolStripItem item)
{
toolStripDropDownButton1.DropDownItems.Add(item);
}
private void onChangesMade()
{
if (null != ChangesMade)
ChangesMade(this, EventArgs.Empty);
}
// Internal status info message text storage
private string statusMessage;
// Internal status info message text property
private string StatusMessageText
{
get { return statusMessage; }
set
{
string tmp = statusMessage;
statusMessage = value;
if (
null != StatusMessageChanged &&
tmp != statusMessage)
StatusMessageChanged(this, new StatusMessageEventArgs(statusMessage));
}
}
/// <summary>
/// CategoryEditor form instance
/// </summary>
private CategoryEditor categoryEditor;
public CategoryBrowser()
{
categoryEditor = new CategoryEditor();
InitializeComponent();
}
// TODO: Use this.BindingContext
[
DescriptionAttribute ("DataSet to bind to. Typed DataSet dbDataSet.xsd expected."),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public dbDataSet DataSource
{
get { return listBox1.DataSource as dbDataSet; }
set
{
listBox1.DataSource = value;
dataSet = (dbDataSet)value;
pcTable = (dbDataSet.productCategoriesDataTable)
dataSet.Tables["productCategories"];
categoryEditor.CategoryNameMaxLength = pcTable.Columns["name"].MaxLength;
categoryEditor.CategoryDescriptionMaxLength = pcTable.Columns["description"].MaxLength;
}
}
/// <summary>
/// Reeturn CurrencyManager due to this.BindingContext
/// </summary>
private CurrencyManager currencyManager
{
get { return (CurrencyManager) this.BindingContext[DataSource, "productCategories"]; }
}
/// <summary>
/// Return current "productCategories" row due to this.BindingContext
/// </summary>
private dbDataSet.productCategoriesRow currentRow
{
get
{
DataRowView view =
(DataRowView)
currencyManager.Current;
return (dbDataSet.productCategoriesRow)view.Row;
}
}
private int pointToIndex(Point loc)
{
if (loc.Y > listBox1.Items.Count * listBox1.ItemHeight)
return ListBox.NoMatches;
else
return listBox1.IndexFromPoint(loc);
}
/// <summary>
/// Handle click (especiali right-button click) on ListBox client area.
/// Switch corresponding context menu.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void contextMenuStrip2_MouseDown(object sender, MouseEventArgs e)
{
int index = pointToIndex (e.Location);
if (index == ListBox.NoMatches)
{
listBox1.ContextMenuStrip = contextMenuStrip1;
}
else
{
listBox1.ContextMenuStrip = contextMenuStrip2;
listBox1.SelectedIndex = index;
}
}
/// <summary>
/// Show dialog "Create new category" dialog
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void createnewToolStripMenuItem_Click(object sender, EventArgs e)
{
// Show dialog
categoryEditor.CategoryIdVisibility = false;
categoryEditor.CategoryName = "<name>";
categoryEditor.CategoryDescription = "";
if (DialogResult.Cancel == categoryEditor.ShowDialog())
return;
// Create row
dbDataSet.productCategoriesRow row =
(dbDataSet.productCategoriesRow)
pcTable.NewRow();
row.name = categoryEditor.CategoryName;
row.description = categoryEditor.CategoryDescription;
pcTable.AddproductCategoriesRow(row);
// Select new row as current
CurrencyManager manager = currencyManager;
manager.Position = manager.Count - 1;
// Advertise changes
onChangesMade();
StatusMessageText = "Added new category (ID = " + currentRow.id.ToString() + ")...";
}
/// <summary>
/// Transform Listbox item index to corresponding DataRow object
/// </summary>
/// <param name="index">ListBox item index</param>
/// <returns>Corresponding DataRow object</returns>
private dbDataSet.productCategoriesRow ListBoxIndexToRow(int index)
{
if (index < 0)
return null;
DataView filter = new DataView(dataSet.Tables["productCategories"]);
filter.RowStateFilter = (DataViewRowState)
(DataRowState.Added |
DataRowState.Modified |
DataRowState.Unchanged);
if (index >= filter.Count)
return null;
dbDataSet.productCategoriesRow row =
(dbDataSet.productCategoriesRow)
filter[index].Row;
if (
row == null ||
(0 != (row.RowState &
(DataRowState.Deleted | DataRowState.Detached))))
return null;
return row;
}
/// <summary>
/// Draw ListBox item. Note, that ListBox.DrawMode must be set to OwnerDrawFixed or OwnerDrawVariable.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
// Read row data
dbDataSet.productCategoriesRow row = ListBoxIndexToRow(e.Index);
if (null == row)
return;
string strName = row.name;
string strId = row.id.ToString();
string strDescription = row.description;
// Init drawing
e.DrawBackground();
Rectangle bounds = e.Bounds;
using (Brush brush = new SolidBrush (Color.Red))
using (Font font = new Font (listBox1.Font, FontStyle.Bold)) {
// Draw category name
Size textSize = TextRenderer.MeasureText(strName, font);
bounds.Height = textSize.Height;
e.Graphics.DrawString(strName, font, brush, bounds);
bounds.X += textSize.Width;
bounds.Width -= textSize.Width;
}
using (Brush brush = new SolidBrush(e.ForeColor))
{
// Draw category ID
string idStr = "(" + strId + ")";
Size textSize = TextRenderer.MeasureText(idStr, listBox1.Font);
e.Graphics.DrawString(idStr, listBox1.Font, brush, bounds);
// Draw category description
bounds.X = e.Bounds.X;
bounds.Y += textSize.Height;
bounds.Width = e.Bounds.Width;
e.Graphics.DrawString(" " + strDescription, listBox1.Font, brush, bounds);
}
e.DrawFocusRectangle();
}
// TODO: Use system-wide implementation of max(a, b)
private T max<T>(T a, T b) where T:IComparable
{
return (a.CompareTo(b)>0) ? a : b;
}
/// <summary>
/// Compute ListBox item width. Note, that ListBox.DrawMode must be set to OwnerDrawVariable.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
// Right margin
// FIXME: This should not be hard-coded
const int iRightMargin = 25;
// Read row data
dbDataSet.productCategoriesRow row = ListBoxIndexToRow(e.Index);
if (null == row)
return;
using (Font font = new Font(listBox1.Font, FontStyle.Bold))
{
// Width: name + id
e.ItemWidth = max(
e.ItemWidth,
TextRenderer.MeasureText(row.name + "(" + row.id + ")", font).Width);
}
// Width: description
e.ItemWidth = max(
e.ItemWidth,
TextRenderer.MeasureText(row.description, listBox1.Font).Width);
// Compare width to recent value and increase if needed
listBox1.HorizontalExtent = max(
listBox1.HorizontalExtent,
e.ItemWidth + iRightMargin);
}
/// <summary>
/// Show CategoryEditor dialog
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void editToolStripMenuItem_Click(object sender, EventArgs e)
{
// Show dialog
categoryEditor.CategoryIdVisibility = true;
categoryEditor.CategoryIdEnabled = false;
categoryEditor.CategoryId = currentRow.id;
categoryEditor.CategoryName = currentRow.name;
categoryEditor.CategoryDescription = currentRow.description;
if (DialogResult.Cancel == categoryEditor.ShowDialog())
return;
// Save changes to DataSet
currentRow.name = categoryEditor.CategoryName;
currentRow.description = categoryEditor.CategoryDescription;
// Advertise changes
onChangesMade();
StatusMessageText = "Changes made to category \"" + currentRow.name + "\" with ID " + currentRow.id.ToString() + "...";
}
/// <summary>
/// Delete category from DataSet (after user confirmation)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
{
// Ask user
string strId = currentRow.id.ToString();
string strName = currentRow.name;
if (DialogResult.Cancel == MessageBox.Show(
"Are you sure to delete product category \"" +
strName + "\"" + " with ID " + strId + "?",
strName,
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation))
return;
DataRow[] childRows = currentRow.GetChildRows(DataSource.Relations[0]);
if (childRows.Length != 0)
{
if (DialogResult.Cancel == MessageBox.Show(
"Category \"" + strName + "\"" + " with ID " + strId +
" is not empty. All products in this category will be deleted!",
strName,
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation))
return;
// Delete products in catefory
foreach (dbDataSet.productsRow row in childRows)
DataSource.products.RemoveproductsRow(row);
}
// Delete category
currentRow.Delete();
// Advertise changes
onChangesMade();
StatusMessageText = "Deleted category \"" + strName + "\" with ID " + strId + "...";
}
/// <summary>
/// Handle double-click on ListBox client area
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_DoubleClick(object sender, MouseEventArgs e)
{
if (ListBox.NoMatches == pointToIndex (e.Location))
return;
editToolStripMenuItem_Click(this, EventArgs.Empty);
}
}
}