Click here to Skip to main content
15,886,799 members
Articles / Web Development / HTML

Signum Framework Tutorials Part 2 – Southwind Logic

Rate me:
Please Sign up or sign in to vote.
4.45/5 (6 votes)
15 Nov 2012LGPL325 min read 31.3K   1K   22  
In this part, we will focus on writing business logic, LINQ queries and explain inheritance
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Collections;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
using System.Windows.Threading;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;

namespace Signum.Windows
{
    //http://www.lazarciuc.ro/ioan/2008/06/01/auto-complete-for-textboxes-in-wpf/
    public partial class AutoCompleteTextBox : UserControl
    {
        public static readonly RoutedEvent ClosedEvent =
            EventManager.RegisterRoutedEvent("Closed", RoutingStrategy.Bubble, typeof(ClosedEventHandler), typeof(AutoCompleteTextBox));
        public event RoutedEventHandler Closed
        {
            add { AddHandler(ClosedEvent, value); }
            remove { RemoveHandler(ClosedEvent, value); }
        }

        public event Func<string, IEnumerable> AutoCompleting;

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(AutoCompleteTextBox), new UIPropertyMetadata(null));
        public object SelectedItem
        {
            get { return (object)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty MinTypedCharactersProperty =
            DependencyProperty.Register("MinTypedCharacters", typeof(int), typeof(AutoCompleteTextBox), new UIPropertyMetadata(2));
        public int MinTypedCharacters
        {
            get { return (int)GetValue(MinTypedCharactersProperty); }
            set { SetValue(MinTypedCharactersProperty, value); }
        }

        DispatcherTimer delayTimer = new DispatcherTimer(DispatcherPriority.Normal);

        public TimeSpan Delay
        {
            get { return delayTimer.Interval; }
            set { delayTimer.Interval = value; }
        }
        
        public AutoCompleteTextBox()
        {
            InitializeComponent();
            delayTimer.Interval = TimeSpan.FromMilliseconds(300);
            itemsSelected = false;
            delayTimer.Tick += new EventHandler(delayTimer_Tick);
        }

        void delayTimer_Tick(object sender, EventArgs e)
        {
            delayTimer.Stop();

            if (AutoCompleting == null) 
                throw new NullReferenceException("SeachMethod cannot be null.");

            IEnumerable res = AutoCompleting(txtBox.Text);


            lstBox.ItemsSource = res;
            if (lstBox.Items.Count > 0)
            {
                lstBox.SelectedIndex = -1;
                pop.IsOpen = true;
            }
            else
            {
                pop.IsOpen = false;
            }
        }

        void MoveDown()
        {
            if (lstBox.SelectedIndex < lstBox.Items.Count - 1)
            {
                lstBox.SelectedIndex++;
            }
        }

        void MoveUp()
        {
            if (lstBox.SelectedIndex > 0)
            {
                lstBox.SelectedIndex--;
            }
        }
    
        void txtBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Up)
            {
                MoveUp();
                e.Handled = true;
            }
            else if (e.Key == Key.Down)
            {
                MoveDown();
                e.Handled = true;
            }
            else if (e.Key == Key.Tab)
            {
                if (lstBox.SelectedItem != null)
                    Commit(CloseReason.Tab);
                else if (lstBox.Items.Count == 1)
                {
                    MoveDown();
                    Commit(CloseReason.Tab);
                }
                else
                    Close(CloseReason.TabExit);

                 txtBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                
                e.Handled = true;
            }
            else if (e.Key == Key.Enter)
            {
                if(lstBox.SelectedItem != null)
                    Commit(CloseReason.Enter);
                else if (lstBox.Items.Count == 1)
                {
                    MoveDown();
                    Commit(CloseReason.Enter);
                }
                
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                Close(CloseReason.Esc);
                e.Handled = true;
            }
           
        }

        void txtBox_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            if (IsTextChangingKey(e.Key))
            {
                Suggest();
            }
        }


        bool IsTextChangingKey(Key key)
        {
            if (key == Key.Back || key == Key.Delete)
                return true;
            else
            
            {
                if (Key.NumPad0 <= key && key <= Key.NumPad9)
                    key += ((int)Key.D0 - (int)Key.NumPad0);

                KeyConverter conv = new KeyConverter();
                string keyString = (string)conv.ConvertTo(key, typeof(string));

                return keyString.Length == 1;
            }
        }

        public void Close(CloseReason reason)
        {
            pop.IsOpen = false;
            RaiseEvent(new CloseEventArgs(reason));
        }


        void Commit(CloseReason reason)
        {
            pop.IsOpen = false;
            if (lstBox.SelectedItem != null)
            {
                txtBox.Text = lstBox.SelectedItem.ToString();

                Close(reason); 

                itemsSelected = true;
            }
        }

        private void txtBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (itemsSelected)
                itemsSelected = false;
            else Suggest();
        }

        private void txtBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!pop.IsKeyboardFocusWithin)
                Close(CloseReason.LostFocus);
        }

        private void Suggest()
        {
            if (txtBox.Text.Length < MinTypedCharacters)
            {
                pop.IsOpen = false;
                lstBox.ItemsSource = null;
                return;
            }

            delayTimer.Start(); 
        }

        private bool itemsSelected;
        private void lstBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (pop.IsKeyboardFocusWithin)
            {
                Commit(CloseReason.ClickList);
            }
        }

        public void SelectAndFocus()
        {
            txtBox.SelectAll();
            txtBox.Focus();
            Mouse.Capture(this, CaptureMode.SubTree); 
        }

        public string Text
        {
            get { return txtBox.Text; }
            set { txtBox.Text = value; }
        }

        private void userControl_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            //Console.WriteLine("Down");
            if (!txtBox.IsMouseOver && !pop.IsMouseOver)
            {
                ReleaseMouseCapture();
                Close(CloseReason.ClickOut);
            }
        }

        //private void me_GotMouseCapture(object sender, MouseEventArgs e)
        //{
        //    Console.WriteLine("Got");
        //}

        //private void me_LostMouseCapture(object sender, MouseEventArgs e)
        //{
        //    Console.WriteLine("Lost");
        //}
    }

    public enum CloseReason
    {
        ClickList,
        Enter,
        Tab,
        TabExit,
        Esc,
        LostFocus,
        ClickOut
    }

    public class CloseEventArgs : RoutedEventArgs
    {
        public CloseReason Reason { get; private set; }
        public bool IsCommit
        {
            get
            {
                return
                    Reason == CloseReason.Enter ||
                    Reason == CloseReason.Tab ||
                    Reason == CloseReason.ClickList;
            }
        }

        public CloseEventArgs(CloseReason reason)
            : base(AutoCompleteTextBox.ClosedEvent)
        {
            Reason = reason;
        }
    }

    public delegate void ClosedEventHandler(object sender, CloseEventArgs e);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) Signum Software
Spain Spain
I'm Computer Scientist, one of the founders of Signum Software, and the lead developer behind Signum Framework.

www.signumframework.com

I love programming in C#, Linq, Compilers, Algorithms, Functional Programming, Computer Graphics, Maths...

Comments and Discussions