4
4
//
5
5
6
6
using System ;
7
+ using System . Collections . Generic ;
8
+ using System . Collections . ObjectModel ;
9
+ using System . Linq ;
7
10
using System . Threading ;
8
11
using System . Threading . Tasks ;
9
12
@@ -37,12 +40,17 @@ public abstract class ChoicePromptHandler : PromptHandler
37
40
{
38
41
#region Private Fields
39
42
40
- private TaskCompletionSource < int > promptTask ;
43
+ private TaskCompletionSource < int [ ] > promptTask ;
41
44
42
45
#endregion
43
46
44
47
#region Properties
45
48
49
+ /// <summary>
50
+ /// Returns true if the choice prompt allows multiple selections.
51
+ /// </summary>
52
+ protected bool IsMultiChoice { get ; private set ; }
53
+
46
54
/// <summary>
47
55
/// Gets the caption (title) string to display with the prompt.
48
56
/// </summary>
@@ -62,7 +70,7 @@ public abstract class ChoicePromptHandler : PromptHandler
62
70
/// Gets the index of the default choice so that the user
63
71
/// interface can make it easy to select this option.
64
72
/// </summary>
65
- protected int DefaultChoice { get ; private set ; }
73
+ protected int [ ] DefaultChoices { get ; private set ; }
66
74
67
75
#endregion
68
76
@@ -102,18 +110,71 @@ public Task<int> PromptForChoice(
102
110
this . Caption = promptCaption ;
103
111
this . Message = promptMessage ;
104
112
this . Choices = choices ;
105
- this . DefaultChoice = defaultChoice ;
106
- this . promptTask = new TaskCompletionSource < int > ( ) ;
113
+ this . promptTask = new TaskCompletionSource < int [ ] > ( ) ;
114
+
115
+ this . DefaultChoices =
116
+ defaultChoice == - 1
117
+ ? new int [ ] { }
118
+ : new int [ ] { defaultChoice } ;
107
119
108
120
// Cancel the TaskCompletionSource if the caller cancels the task
109
121
cancellationToken . Register ( this . CancelPrompt , true ) ;
110
122
111
123
// Show the prompt to the user
112
124
this . ShowPrompt ( PromptStyle . Full ) ;
113
125
114
- return this . promptTask . Task ;
126
+ // Convert the int[] result to int
127
+ return this . promptTask . Task . ContinueWith (
128
+ t => t . Result . DefaultIfEmpty ( - 1 ) . First ( ) ) ;
115
129
}
116
130
131
+ /// <summary>
132
+ /// Prompts the user to make a choice of one or more options using the
133
+ /// provided details.
134
+ /// </summary>
135
+ /// <param name="promptCaption">
136
+ /// The caption string which will be displayed to the user.
137
+ /// </param>
138
+ /// <param name="promptMessage">
139
+ /// The descriptive message which will be displayed to the user.
140
+ /// </param>
141
+ /// <param name="choices">
142
+ /// The list of choices from which the user will select.
143
+ /// </param>
144
+ /// <param name="defaultChoices">
145
+ /// The default choice(s) to highlight for the user.
146
+ /// </param>
147
+ /// <param name="cancellationToken">
148
+ /// A CancellationToken that can be used to cancel the prompt.
149
+ /// </param>
150
+ /// <returns>
151
+ /// A Task instance that can be monitored for completion to get
152
+ /// the user's choices.
153
+ /// </returns>
154
+ public Task < int [ ] > PromptForChoice (
155
+ string promptCaption ,
156
+ string promptMessage ,
157
+ ChoiceDetails [ ] choices ,
158
+ int [ ] defaultChoices ,
159
+ CancellationToken cancellationToken )
160
+ {
161
+ // TODO: Guard against multiple calls
162
+
163
+ this . Caption = promptCaption ;
164
+ this . Message = promptMessage ;
165
+ this . Choices = choices ;
166
+ this . DefaultChoices = defaultChoices ;
167
+ this . IsMultiChoice = true ;
168
+ this . promptTask = new TaskCompletionSource < int [ ] > ( ) ;
169
+
170
+ // Cancel the TaskCompletionSource if the caller cancels the task
171
+ cancellationToken . Register ( this . CancelPrompt , true ) ;
172
+
173
+ // Show the prompt to the user
174
+ this . ShowPrompt ( PromptStyle . Full ) ;
175
+
176
+ return this . promptTask . Task ;
177
+ }
117
178
/// <summary>
118
179
/// Implements behavior to handle the user's response.
119
180
/// </summary>
@@ -124,29 +185,41 @@ public Task<int> PromptForChoice(
124
185
/// </returns>
125
186
public override bool HandleResponse ( string responseString )
126
187
{
127
- int choiceIndex = - 1 ;
188
+ List < int > choiceIndexes = new List < int > ( ) ;
128
189
129
- // Clean up the response string
130
- responseString = responseString . Trim ( ) ;
190
+ // Clean up the response string and split it
191
+ var choiceStrings =
192
+ responseString . Trim ( ) . Split (
193
+ new char [ ] { ',' } ,
194
+ StringSplitOptions . RemoveEmptyEntries ) ;
131
195
132
- for ( int i = 0 ; i < this . Choices . Length ; i ++ )
196
+ foreach ( string choiceString in choiceStrings )
133
197
{
134
- if ( this . Choices [ i ] . MatchesInput ( responseString ) )
198
+ for ( int i = 0 ; i < this . Choices . Length ; i ++ )
135
199
{
136
- choiceIndex = i ;
137
- break ;
200
+ if ( this . Choices [ i ] . MatchesInput ( choiceString ) )
201
+ {
202
+ choiceIndexes . Add ( i ) ;
203
+
204
+ // If this is a single-choice prompt, break out after
205
+ // the first matched choice
206
+ if ( ! this . IsMultiChoice )
207
+ {
208
+ break ;
209
+ }
210
+ }
138
211
}
139
212
}
140
213
141
- if ( choiceIndex == - 1 )
214
+ if ( choiceIndexes . Count == 0 )
142
215
{
143
216
// The user did not respond with a valid choice,
144
217
// show the prompt again to give another chance
145
218
this . ShowPrompt ( PromptStyle . Minimal ) ;
146
219
return false ;
147
220
}
148
221
149
- this . promptTask . SetResult ( choiceIndex ) ;
222
+ this . promptTask . SetResult ( choiceIndexes . ToArray ( ) ) ;
150
223
return true ;
151
224
}
152
225
0 commit comments