diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs index a7b1e005..0918f245 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/TokenizedTextBox/Implementation/TokenizedTextBox.cs @@ -26,7 +26,7 @@ namespace Microsoft.Windows.Controls { get { return (string)GetValue(SearchMemberPathProperty); } set { SetValue(SearchMemberPathProperty, value); } - } + } public static readonly DependencyProperty TokenDelimiterProperty = DependencyProperty.Register("TokenDelimiter", typeof(string), typeof(TokenizedTextBox), new UIPropertyMetadata(";")); public string TokenDelimiter @@ -74,7 +74,7 @@ namespace Microsoft.Windows.Controls get { return (string)GetValue(ValueMemberPathProperty); } set { SetValue(ValueMemberPathProperty, value); } } - + #endregion //Properties @@ -99,10 +99,16 @@ namespace Microsoft.Windows.Controls base.OnApplyTemplate(); if (_rtb != null) - _rtb.TextChanged -= OnTextChanged; + { + _rtb.TextChanged -= RichTextBox_TextChanged; + _rtb.PreviewKeyDown -= RichTextBox_PreviewKeyDown; + } _rtb = GetTemplateChild("PART_ContentHost") as System.Windows.Controls.RichTextBox; if (_rtb != null) - _rtb.TextChanged += OnTextChanged; + { + _rtb.TextChanged += RichTextBox_TextChanged; + _rtb.PreviewKeyDown += RichTextBox_PreviewKeyDown; + } InitializeTokensFromText(); } @@ -111,7 +117,7 @@ namespace Microsoft.Windows.Controls #region Event Handlers - private void OnTextChanged(object sender, TextChangedEventArgs e) + private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e) { if (_surpressTextChangedEvent) return; @@ -124,6 +130,39 @@ namespace Microsoft.Windows.Controls } } + void RichTextBox_PreviewKeyDown(object sender, KeyEventArgs e) + { + InlineUIContainer container = null; + + if (e.Key == Key.Back) + { + container = _rtb.CaretPosition.GetAdjacentElement(LogicalDirection.Backward) as InlineUIContainer; + } + else if (e.Key == Key.Delete) + { + //if the selected text is a blank space, I will assume that a token item is selected. + //if a token item is selected, we need to move the caret position to the left of the element so we can grab the InlineUIContainer + if (_rtb.Selection.Text == " ") + { + TextPointer moveTo = _rtb.CaretPosition.GetNextInsertionPosition(LogicalDirection.Backward); + _rtb.CaretPosition = moveTo; + } + + //the cursor is to the left of a token item + container = _rtb.CaretPosition.GetAdjacentElement(LogicalDirection.Forward) as InlineUIContainer; + } + + //if the container is not null that means we have something to delete + if (container != null) + { + var token = (container as InlineUIContainer).Child as TokenItem; + if (token != null) + { + SetTextInternal(Text.Replace(token.TokenKey, "")); + } + } + } + #endregion //Event Handlers #region Methods @@ -136,8 +175,8 @@ namespace Microsoft.Windows.Controls foreach (string tokenKey in tokenKeys) { var para = _rtb.CaretPosition.Paragraph; - var token = new Token(TokenDelimiter) - { + var token = new Token(TokenDelimiter) + { TokenKey = tokenKey, Item = ResolveItemByTokenKey(tokenKey) }; @@ -157,7 +196,7 @@ namespace Microsoft.Windows.Controls private Token ResolveTokenBySearchMemberPath(string searchText) { //create a new token and default the settings to the search text - var token = new Token(TokenDelimiter) + var token = new Token(TokenDelimiter) { TokenKey = searchText, Item = searchText @@ -252,11 +291,11 @@ namespace Microsoft.Windows.Controls { object item = token.Item; - var tokenItem = new TokenItem() - { - TokenKey = token.TokenKey, - Content = item, - ContentTemplate = TokenTemplate + var tokenItem = new TokenItem() + { + TokenKey = token.TokenKey, + Content = item, + ContentTemplate = TokenTemplate }; if (TokenTemplate == null)