BindingContext – List controls that share a datasource

This one had me stumped for a while! If you have multiple list controls (combo’s etc) on the same form set to the same datasource, the default behaviour is for the controls to share the form’s BindingContext ,thus synchronising the current position. This means when you change list position in say ‘Combo A’, the selected index is also changed in ‘Combo B’.

To avoid this behaviour requires just one line of code applied to at least one of your controls.
Phew!


comboBox1.BindingContext = new BindingContext();

Advertisements

Custom Messagebox

9 times out of 10 the standard Windows Forms messagebox will do, but for those occasions it won’t, it’s pretty straight forward to design your own. I have an enum ‘MyMessageBoxButtons’ set up to accept ‘ok’ and ‘okCancel’, I have also set the OK button to fill the width of it’s parent panel if it is the only button to be displayed (this messagebox form is being displayed full screen in a mobile application), but you get the idea.


public partial class MyMessagebox : Form
{
    private static MyMessagebox messageBox;
    private static DialogResult messageboxResult;

    public MyMessagebox ()
    {
        InitializeComponent();
    }

    public static DialogResult Show(string messageText)
    {
        messageBox = new MyMessagebox ();
        messageBox.lbMessageboxMessage.Text = messageText;
        ShowButtons(messageBox, MyMessageBoxButtons.Ok);
        messageBox.ShowDialog();

        return messageboxResult;
    }

    public static DialogResult Show(string messageText, string messageCaption, MyMessageBoxButtons buttons)
    {
        messageBox = new myMessagebox();
        messageBox.lbMessageboxMessage.Text = messageText;
        messageBox.lbMessageboxCaption.Text = messageCaption;
        ShowButtons(messageBox, buttons);
        messageBox.ShowDialog();

        return messageboxResult;
    }
    
    private static void ShowButtons(MyMessageBox myMessageBox, MyMessageBoxButtons buttons)
    {
        myMessageBox.btnMessageboxOk.Enabled = true;
        myMessageBox.btnMessageboxOk.Visible = true;

        if (buttons != MyMessageBoxButtons.Ok)
        {
            myMessageBox.btnMessageboxCancel.Enabled = true;
            myMessageBox.btnMessageboxCancel.Visible = true;
        }
        else
        {
            myMessageBox.btnMessageboxOk.Width = myMessageBox.pnMessageboxDetail.Width;
        }
    }

    private void btnMessageboxOk_Click(object sender, EventArgs e)
    {
        messageboxResult = DialogResult.OK;
        messageBox.Close();
    }

    private void btnMessageboxCancel_Click(object sender, EventArgs e)
    {
        messageboxResult = DialogResult.Cancel;
        messageBox.Close();
    }        
}

Using Reflection to open a form by name

Here is a quick example of how the System.Reflection namespace can be utilised to open form instances in a method that accepts the form name as a string. It also shows how you can pass across variables to forms with overloaded constructors.

It’s particularly useful when working with a main menu structure, such as I have in a current project loaded into a Treeview.


private void LoadNewForm(string formName)
{
    try
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        Type type = assembly.GetType(formName);

        //for this form I have an overloaded constructor, accepting a 'User' object
        ConstructorInfo ci = type.GetConstructor(new Type[1] { typeof(User) }); 
        object[] argVals = new object[] { CurrentUser };  //pass 'CurrentUser' variable to form constructor
        Form frm = (Form)ci.Invoke(argVals);

        frm.Show();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
} 

Scrolling a picturebox

Can’t be bothered extending the picturebox control to allow scrolling?…me either! Dump a panel on a form and set it’s ‘AutoScroll’ property to true, now place a picturebox on this panel and set it’s SizeMode to ‘AutoSize’. And there you have it, a scrollable picturebox without writing a single line of code!…just the way I like it! 🙂

Drag and Drop from TreeView

This is pretty straight forward, in the sample code below it shows how to add a TreeView node with an image into a ListBox. You’ll need an ImageList loaded with images to link both the TreeView and ListBox to and set the ListView to a view that allows images, i.e ‘Tile’.

private TreeNode sourceNode;

private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    sourceNode = (TreeNode)e.Item;

    if (sourceNode.Parent != null)
        DoDragDrop(sourceNode, DragDropEffects.Move);
}

private void DragEnter_Event(object sender, DragEventArgs e)
{
    if (e.Data.GetData(typeof(TreeNode)) != null)
        e.Effect = DragDropEffects.Move;
    else
        e.Effect = DragDropEffects.None;
}

private void listView1_DragDrop(object sender, DragEventArgs e)
{
    listView.Items.Add(sourceNode.Text, sourceNode.ImageIndex);
}

Just add the DragEnter event to the _DragEnter event of the controls you want to allow the DragDropEffects.Move to show on.

Minimize application to System Tray

A quick snippet to show how to minimize an application to the Windows System Tray using a NotifyIcon. Set the NotifyIcon text to be whatever you want displayed when you hover over it in the System Tray and be sure to set the Icon property too, else nothing will get displayed! Then add the following in the form_resize event:

private void wfMain_Resize(object sender, EventArgs e)
{
    if (FormWindowState.Minimized == WindowState)
        Hide();
}

And to restore it to it’s former state. simply add the following in the DoubleClick event of your NotifyIcon:

private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
    this.Show();
    WindowState = FormWindowState.Normal;
}

Decimal TextBox Mk2

Decided my decimal textbox was a bit shit so had another quick go this afternoon, this time I did away with pasting altogether and disabled right click on the control by creating a blank contextmenu and assigning it to the textbox. Anyway here it is:


using System;
using System.Windows.Forms;

namespace DecimalTextBox
{
    public partial class DTB : TextBox
    {
        public int DecimalLength { get; set; }
        int[] numZeros;
        ContextMenu cmPaste = new ContextMenu();

        public DTB()
        {
            this.ContextMenu = cmPaste;  
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            e.Handled = CheckDecimal(this, e, DecimalLength);
        }

        protected override void OnLeave(EventArgs e)
        {
            if (this.Text == "")
                this.Text += "0";
            if (this.Text.IndexOf(".") == -1)
                this.Text += ".";
                        
            numZeros = new int[this.Text.IndexOf(".") + DecimalLength - this.Text.Length + 1];

            if (this.Text.IndexOf(".") >= this.Text.Length - DecimalLength)
            {
                for (int i = 0; i < numZeros.Length; i++)
                {
                    numZeros[i] = 0;
                    this.Text += numZeros[i];
                }
            }
        }
        
        private static bool CheckDecimal(object sender, KeyPressEventArgs e, int numDecimals)
        {
            if (char.IsNumber(e.KeyChar) || e.KeyChar == '.')
            {
                TextBox tb = sender as TextBox;
                int cursorPosLeft = tb.SelectionStart;
                int cursorPosRight = tb.SelectionStart + tb.SelectionLength;
 
                string result = tb.Text.Substring(0, cursorPosLeft) + e.KeyChar + tb.Text.Substring(cursorPosRight);
                string[] parts = result.Split('.');
                
                if (parts.Length > 1)
                {
                    if (parts[1].Length > numDecimals || parts.Length > 2)
                    {
                        return true;
                    }
                }
                return false;
            }
            else return (e.KeyChar != (char)Keys.Back);
        }
    }
}