Skip to content

Commit 1634f50

Browse files
author
Declan Taylor
committed
Adds new dependency property to SuggestBoxBase,IsValidationByTextBinding, which directs the control to use Validation binding over IsValidText property.
Changes IsPopupOpened dependency property to IsPopupOpen in SuggestBoxBase. Adds event, QueryChangedEvent, to SuggestBox as an alternative to use of TextChangedCommand.
1 parent 935b6dc commit 1634f50

File tree

3 files changed

+1205
-1213
lines changed

3 files changed

+1205
-1213
lines changed

source/SuggestBoxLib/SuggestBox.cs

Lines changed: 120 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,147 +1,123 @@
11
namespace SuggestBoxLib
22
{
3-
using Interfaces;
4-
using System.Windows;
5-
using System.Windows.Controls;
6-
using System.Windows.Input;
7-
8-
/// <summary>
9-
/// Implements a text based control that updates a list of suggestions
10-
/// when user updates a given text based path -> TextChangedEvent is raised.
11-
///
12-
/// This control uses <see cref="ISuggestSource"/> and HierarchyHelper
13-
/// to suggest entries in a seperate popup as the user types.
14-
/// </summary>
15-
public class SuggestBox : SuggestBoxBase
16-
{
17-
#region fields
18-
19-
/// <summary>
20-
/// Implements the backing store for the <see cref="TextChangedCommand"/> dependency property.
21-
/// </summary>
22-
public static readonly DependencyProperty TextChangedCommandProperty =
23-
DependencyProperty.Register("TextChangedCommand",
24-
typeof(ICommand), typeof(SuggestBox), new PropertyMetadata(null));
25-
26-
#endregion fields
27-
28-
#region Constructor
29-
30-
/// <summary>
31-
/// Static class constructor.
32-
/// </summary>
33-
static SuggestBox()
34-
{
35-
DefaultStyleKeyProperty.OverrideMetadata(typeof(SuggestBox),
36-
new FrameworkPropertyMetadata(typeof(SuggestBox)));
37-
}
38-
39-
/// <summary>
40-
/// Class constructor
41-
/// </summary>
42-
public SuggestBox()
43-
{
44-
IsVisibleChanged += SuggestBox_IsVisibleChanged;
45-
}
46-
47-
#endregion Constructor
48-
49-
#region Public Properties
50-
51-
/// <summary>
52-
/// Gets/sets a command that should be executed whenever the text in the textbox
53-
/// portion of this control has changed.
54-
/// </summary>
55-
public ICommand TextChangedCommand
56-
{
57-
get { return (ICommand)GetValue(TextChangedCommandProperty); }
58-
set { SetValue(TextChangedCommandProperty, value); }
59-
}
60-
61-
#endregion Public Properties
62-
63-
#region Methods
64-
65-
/// <summary>
66-
/// Method executes when the <see cref="SuggestBoxBase.EnableSuggestions"/> dependency property
67-
/// has changed its value.
68-
///
69-
/// Overwrite this method if you want to consume changes of this property.
70-
/// </summary>
71-
/// <param name="e"></param>
72-
override protected void OnEnableSuggestionChanged(DependencyPropertyChangedEventArgs e)
73-
{
74-
base.OnEnableSuggestionChanged(e);
75-
76-
if (((bool)e.NewValue) == true)
77-
QueryForSuggestions();
78-
}
79-
80-
/// <summary>
81-
/// Method executes when the visibility of the control is changed to query for
82-
/// suggestions if this was enabled...
83-
/// </summary>
84-
/// <param name="sender"></param>
85-
/// <param name="e"></param>
86-
private void SuggestBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
87-
{
88-
if (((bool)e.NewValue) == true)
89-
QueryForSuggestions();
90-
}
91-
92-
/// <summary>
93-
/// Method executes when new text is entered in the textbox portion of the control.
94-
/// </summary>
95-
/// <param name="e"></param>
96-
protected override void OnTextChanged(TextChangedEventArgs e)
97-
{
98-
base.OnTextChanged(e);
99-
100-
if (string.IsNullOrEmpty(this.Text) == false)
101-
IsHintVisible = false;
102-
else
103-
IsHintVisible = true;
104-
105-
QueryForSuggestions();
106-
}
107-
108-
private void QueryForSuggestions()
109-
{
110-
// A change during disabled state is likely to be caused by a bound property
111-
// in a viewmodel (a machine based edit rather than user input)
112-
// -> Lets break the message loop here to avoid unnecessary CPU processings...
113-
if (this.IsEnabled == false || this.IsLoaded == false)
114-
return;
115-
116-
// Text change is likely to be from property change so we ignore it
117-
// if control is invisible or suggestions are currently not requested
118-
if (Visibility != Visibility.Visible || EnableSuggestions == false)
119-
return;
120-
121-
if (ParentWindowIsClosing == true)
122-
return;
123-
124-
ICommand changedCommand = this.TextChangedCommand;
125-
126-
// There may not be a command bound to this after all
127-
if (changedCommand == null)
128-
return;
129-
130-
var item = this.Text;
131-
132-
// Check whether this attached behaviour is bound to a RoutedCommand
133-
if (changedCommand is RoutedCommand)
134-
{
135-
// Execute the routed command
136-
(changedCommand as RoutedCommand).Execute(item, this);
137-
}
138-
else
139-
{
140-
// Execute the Command as bound delegate
141-
changedCommand.Execute(item);
142-
}
143-
}
144-
145-
#endregion Methods
146-
}
3+
using Interfaces;
4+
using System.Windows;
5+
using System.Windows.Controls;
6+
using System.Windows.Input;
7+
8+
/// <summary>
9+
/// Implements a text based control that updates a list of suggestions
10+
/// when user updates a given text based path -> TextChangedEvent is raised.
11+
///
12+
/// This control uses <see cref="ISuggestSource"/> and HierarchyHelper
13+
/// to suggest entries in a separate popup as the user types.
14+
/// </summary>
15+
public class SuggestBox : SuggestBoxBase
16+
{
17+
#region fields
18+
public static readonly RoutedEvent QueryChangedEvent = EventManager.RegisterRoutedEvent(nameof(QueryChanged), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<string>), typeof(SuggestBox));
19+
public static readonly DependencyProperty TextChangedCommandProperty = DependencyProperty.Register(nameof(TextChangedCommand), typeof(ICommand), typeof(SuggestBox), new PropertyMetadata(null));
20+
21+
public event RoutedPropertyChangedEventHandler<string> QueryChanged
22+
{
23+
add => AddHandler(QueryChangedEvent, value);
24+
remove => RemoveHandler(QueryChangedEvent, value);
25+
}
26+
27+
#endregion fields
28+
29+
#region Constructor
30+
static SuggestBox()
31+
{
32+
DefaultStyleKeyProperty.OverrideMetadata(typeof(SuggestBox), new FrameworkPropertyMetadata(typeof(SuggestBox)));
33+
}
34+
35+
public SuggestBox()
36+
{
37+
IsVisibleChanged += SuggestBox_IsVisibleChanged;
38+
}
39+
40+
#endregion Constructor
41+
42+
#region Public Properties
43+
44+
/// <summary>
45+
/// Gets/sets a command that should be executed whenever the text in the textbox
46+
/// portion of this control has changed.
47+
/// </summary>
48+
public ICommand TextChangedCommand
49+
{
50+
get { return (ICommand)GetValue(TextChangedCommandProperty); }
51+
set { SetValue(TextChangedCommandProperty, value); }
52+
}
53+
54+
#endregion Public Properties
55+
56+
#region Methods
57+
58+
/// <summary>
59+
/// Method executes when the <see cref="SuggestBoxBase.EnableSuggestions"/> dependency property has changed its value.
60+
/// </summary>
61+
protected override void OnEnableSuggestionChanged(DependencyPropertyChangedEventArgs e)
62+
{
63+
base.OnEnableSuggestionChanged(e);
64+
65+
if ((bool)e.NewValue == true)
66+
QueryForSuggestions();
67+
}
68+
69+
/// <summary>
70+
/// Method executes when the visibility of the control is changed to query for
71+
/// suggestions if this was enabled...
72+
/// </summary>
73+
private void SuggestBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
74+
{
75+
if (((bool)e.NewValue) == true)
76+
QueryForSuggestions();
77+
}
78+
79+
/// <summary>
80+
/// Method executes when new text is entered in the textbox portion of the control.
81+
/// </summary>
82+
protected override void OnTextChanged(TextChangedEventArgs e)
83+
{
84+
base.OnTextChanged(e);
85+
86+
IsHintVisible = string.IsNullOrEmpty(this.Text);
87+
88+
QueryForSuggestions();
89+
}
90+
91+
private void QueryForSuggestions()
92+
{
93+
// A change during disabled state is likely to be caused by a bound property
94+
// in a viewmodel (a machine based edit rather than user input)
95+
// -> Lets break the message loop here to avoid unnecessary CPU processings...
96+
if (this.IsEnabled == false || this.IsLoaded == false)
97+
return;
98+
99+
// Text change is likely to be from property change so we ignore it
100+
// if control is invisible or suggestions are currently not requested
101+
if (Visibility != Visibility.Visible || EnableSuggestions == false)
102+
return;
103+
104+
if (ParentWindowIsClosing)
105+
return;
106+
107+
this.RaiseEvent(new RoutedPropertyChangedEventArgs<string>(string.Empty, Text, QueryChangedEvent));
108+
109+
// Check whether this attached behaviour is bound to a RoutedCommand
110+
if (this.TextChangedCommand is RoutedCommand command)
111+
{
112+
// Execute the routed command
113+
command.Execute(this.Text, this);
114+
}
115+
else
116+
{
117+
// Execute the Command as bound delegate if anything bound
118+
TextChangedCommand?.Execute(this.Text);
119+
}
120+
}
121+
#endregion Methods
122+
}
147123
}

source/SuggestBoxLib/SuggestBoxBase.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
x:Name="PART_Popup"
4949
AllowsTransparency="true"
5050
Focusable="False"
51-
IsOpen="{Binding IsPopupOpened, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
51+
IsOpen="{Binding IsPopupOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
5252
Placement="Bottom"
5353
PlacementTarget="{Binding ElementName=PART_ContentHost}"
5454
PopupAnimation="None"

0 commit comments

Comments
 (0)