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

Compact Framework – Increasing ScrollBar Width

The Datagrid in the Compact Framework has fixed 13 pixel wide/tall scrollbars but no way to resize them. Creating a control that inherits from Datagrid, overriding the size of the scrollbars would be one way to go, but it can be achieved without the need to do this by using reflection.


FieldInfo fieldInfo = dgBinDetail.GetType().GetField("m_sbVert", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);

((VScrollBar)fieldInfo.GetValue(dgBinDetail)).Width = 30; 

Remember to add the System.Reflection namespace to your list of using statements at the top of your class.

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);
        }
    }
}

Prevent Form being moved

I recently had a need to dock a form to the right hand side of the screen and prevent users from dragging it away. The form can be minimised into the system tray but not resized or moved, of course I could have removed the forms control box and drawn my own but wanted it to fit with the other forms in the project.

Method 1: Override WndProc.

protected override void WndProc(ref Message msg)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MOVE = 0xF010;

    switch (msg.Msg)
    {
        case WM_SYSCOMMAND:
            int cmd = msg.WParam.ToInt32() & 0xfff0;
    
            if (cmd == SC_MOVE)
                return;
        
            break;
    }

    base.WndProc(ref msg);
}

Method 2: This is the preferred method and allows the form to be dragged onto multiple monitors but will always dock to the right hand side of whichever screen it is dragged to.

private const int scrnBuffer = 5;
private Screen scrn;

private void Form1_Move(object sender, EventArgs e)
{
    SizeForms();
}

private void SizeForms()
{
    scrn = Screen.FromControl(this);

    this.Height = scrn.WorkingArea.Height - scrnBuffer * 2;
    this.Location = new Point(scrn.WorkingArea.Right - this.Width - scrnBuffer, scrn.WorkingArea.Top + scrnBuffer);
}