|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml;
using System.Collections.ObjectModel;
using System.Windows;
namespace CommonUtils
{
[TemplatePart(Name="PART_Popup", Type=typeof(HistoryListPopup))]
public class TextBoxWithHistory : TextBox
{
HistoryList m_history;
Button m_dropButton;
HistoryListPopup m_popup;
static TextBoxWithHistory()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxWithHistory), new FrameworkPropertyMetadata(typeof(TextBoxWithHistory)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Popup = Template.FindName("PART_Popup", this) as HistoryListPopup;
m_dropButton = Template.FindName("PART_DropButton", this) as Button;
if (m_dropButton != null)
m_dropButton.Click += OnDropButtonClick;
}
public HistoryListPopup Popup
{
get { return m_popup;}
private set
{
if (m_popup != null)
m_popup.Closed -= OnPopupClosed;
m_popup = value;
if (m_popup != null)
{
m_popup.Closed += OnPopupClosed;
if (History != null)
Popup.HistoryList = m_history.Items;
}
}
}
public HistoryList History
{
get
{
return m_history;
}
set
{
m_history = value;
if (Popup != null)
Popup.HistoryList = m_history.Items;
}
}
public void AddToHistory(string text, bool clearText)
{
History.Add(text);
if (clearText)
Text = string.Empty;
}
public TextBoxWithHistory()
{
History = new HistoryList();
}
string m_saved = string.Empty;
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
//Console.WriteLine("{0}: Key {1}, SystemKey {2}", DateTime.Now.ToLongTimeString(), e.Key, e.SystemKey);
if (e.Key == Key.Escape && IsFocused)
{
History.Reset();
Text = string.Empty;
if (Popup != null)
Popup.Close(false);
e.Handled = true;
return;
}
if (e.Key == Key.Up && IsFocused)
{
if (History.CurIndex < 0)
m_saved = Text;
string text = string.Empty;
if (History.Prev(out text))
{
Text = text;
CaretIndex = Text.Length;
SelectAll();
}
e.Handled = true;
return;
}
if (e.Key == Key.Down && IsFocused)
{
string text = string.Empty;
if (History.Next(out text))
{
if (History.CurIndex < 0)
text = m_saved;
Text = text;
CaretIndex = Text.Length;
SelectAll();
}
e.Handled = true;
return;
}
if (e.Key == Key.Left || e.Key == Key.Right)
{
// any left / right will reset the history index and clear the 'saved'
History.Reset();
m_saved = string.Empty;
}
if (e.SystemKey == Key.Down && e.KeyboardDevice.Modifiers == ModifierKeys.Alt)
{
if (IsFocused)
{
OnDropButtonClick(null, null);
e.Handled = true;
return;
}
}
base.OnPreviewKeyDown(e);
}
void OnDropButtonClick(object sender, EventArgs e)
{
if (Popup != null)
Popup.Open(Text);
}
void OnPopupClosed(object sender, EventArgs e)
{
HistoryListPopup popup = sender as HistoryListPopup;
if (popup.PopupResult)
{
Text = popup.SelectedItem;
CaretIndex = Text.Length;
}
Focus();
}
}
public class HistoryList
{
public int CurIndex {get; private set;}
public int MaxCount {get; set;}
public ObservableCollection<string> Items {get; set;}
public HistoryList()
{
Items = new ObservableCollection<string>();
MaxCount = 50;
}
public void Add(string text)
{
text = text.Trim();
if (text.Length == 0)
return;
int index = Items.IndexOf(text);
if (index > 0)
Items.RemoveAt(index);
if (index != 0)
Items.Insert(0, text);
Items.Truncate(MaxCount);
Reset();
}
public bool Prev(out string value)
{
value = string.Empty;
if (CurIndex < Items.Count - 1)
{
CurIndex++;
if (CurIndex >= 0 && CurIndex < Items.Count)
{
value = Items[CurIndex];
return true;
}
}
return false;
}
public bool Next(out string value)
{
value = string.Empty;
if (CurIndex >= 0)
{
CurIndex--;
if (CurIndex >= 0 && CurIndex < Items.Count)
value = Items[CurIndex];
return true;
}
return false;
}
public void Reset()
{
CurIndex = -1;
}
public void Clear()
{
Items.Clear();
Reset();
}
public void Write(XmlTextWriter wr, string name)
{
wr.WriteStartElement("list");
if (name.Length > 0)
wr.WriteAttributeString("name", name);
foreach (string hist in Items)
wr.WriteElementString("item", hist);
wr.WriteEndElement();
}
public void Read(XmlElement node)
{
if (node == null)
return;
Clear();
System.Diagnostics.Debug.Assert(node.Name == "list");
foreach (XmlElement child in node.ChildNodes)
{
if (child.Name == "item")
Items.Add(child.InnerText);
}
}
}
public class HistoryListPopup : System.Windows.Controls.Primitives.Popup
{
ListBox m_historyListBox = null;
public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(string), typeof(HistoryListPopup));
ObservableCollection<string> m_list;
public bool PopupResult {get; protected set;}
public string SelectedItem
{
get { return (string)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public ObservableCollection<string> HistoryList
{
get { return m_list;}
set
{
m_list = value;
DataContext = this;
}
}
public HistoryListPopup()
{
SelectedItem = string.Empty;
Loaded += new RoutedEventHandler(OnLoaded);
}
void OnLoaded(object sender, RoutedEventArgs e)
{
if (m_historyListBox != null)
return;
m_historyListBox = VisualTreeUtils.FindVisualChildByName<ListBox>(Child, "m_historyListBox");
if (m_historyListBox != null)
{
// cool, attach and receive event even if it has been handled (true)
m_historyListBox.AddHandler(ListBox.MouseLeftButtonDownEvent,
(RoutedEventHandler)OnLeftButtonDown,
true);
}
}
void OnLeftButtonDown(object sender, RoutedEventArgs e)
{
Close(SelectedItem.Length > 0);
}
public virtual void Open(string curText)
{
SelectedItem = curText;
IsOpen = true;
ListBox lb = Child as ListBox;
if (lb != null)
{
lb.Focus();
ListBoxItem item = lb.ItemContainerGenerator.ContainerFromItem(lb.SelectedItem) as ListBoxItem;
if (item != null)
item.Focus();
else if (HistoryList.Count > 0)
item = lb.ItemContainerGenerator.ContainerFromItem(HistoryList[0]) as ListBoxItem;
if (item != null)
item.Focus();
}
}
public virtual void Close(bool result)
{
PopupResult = result;
IsOpen = false;
UIElement target = PlacementTarget;
if (target != null)
target.Focus();
}
protected override void OnOpened(EventArgs e)
{
PopupResult = false;
base.OnOpened(e);
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
if (e.Key == Key.Escape)
{
Close(false);
return;
}
if (e.Key == Key.Enter)
{
Close(true);
return;
}
}
}
}
|
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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.