Partager via


Confirmation with QuestionAnswerActivity

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

The example discussed in this topic mimics to a large degree the behavior of the GetAndConfirmActivity discussed in Confirmation with GetAndConfirmActivity. However, instead of using a single GetAndConfirmActivity to obtain and then confirm a user's response, you can use one or more QuestionAnswerActivity objects to obtain the semantic items from the user's response and a single QuestionAnswerActivity to confirm them all.

Dialog Flow

Bb800819.709fdc4f-c523-44fc-b574-2caa82f2e673(en-us,office.12).jpg

The preceding illustration shows the dialog elements and their relationship to each other. After the call is answered, the askCityQuestionAnswerActivity asks the user to choose a city from a list of cities that it plays. If the confidence of the recognition is suitably high, the confirmCityQuestionAnswerActivity restates the user's selected city and asks the user to confirm it. If the user confirms that choice, the sayByeByeStatementActivity says the city one more time before saying goodbye to the user. If the user does not confirm the result that the application recognized, the goToAskCityGoToActivity branches back to getCity, which restarts the process. If the user explicitly denies a city that the application recognized, the application does not play that city's name in subsequent prompts.

Application Data

The data used in this example includes _city, which is a SemanticItem<string> value, and _cityList, which is an array of type string. _cityList contains the names of several cities.

private SemanticItem<string> _city; 
public string[] _cityList = new string[] { "Albany", "Butte", "Chicago", "Dover", "Ephrata", "Ferndale", "Grand Rapids", "Helena" };

Dialog Flow in Detail

The TurnStarting event handler for askCity, askCity_TurnStarting, prompts the user to choose a city from those on the list of cities that it plays. The only unusual issue is that if a city was recognized in a previous turn, but the user did not confirm it, that city's name is not played in subsequent turns. As discussed later in this topic, if a city is not confirmed, Deny is called on the _city semantic item, which causes that particular semantic item to be added to the DeniedValues collection.

private void askCity_TurnStarting(object sender, TurnStartingEventArgs e)
{
  this.askCity.MainPrompt.SetText("Choose the name of a city from the following list ");
  this.askCity.MainPrompt.AppendBreak(TimeSpan.FromMilliseconds(200));
  // Iterate through the _cityList array, prompting for those cities not on the 
  // DeniedValues list. There is no logic here for the case where all of the cities 
  // have been denied.
  for (int idx = 0; idx < _cityList.Length; idx++)
  {
    if (_city.DeniedValues.Count == 0 || !_city.DeniedValues.Contains(_cityList[idx]))
    {
      this.askCity.MainPrompt.AppendText(_cityList[idx]);
      this.askCity.MainPrompt.AppendBreak(TimeSpan.FromMilliseconds(150)); 
    }
  }
}

The event handler code that follows executes when the Closed event is raised by getCity. Because there is no support for the Closed event, you need to add the following line of code to the workflow constructor, immediately following the call to InitializeComponent().

this.askCity.Closed += new System.EventHandler<System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs>(this.askCity_Closed);

If the Confidence of the recognition result is less than or equal to the semantic item's ConfirmThreshold, the event handler calls Update on the semantic item to indicate that the semantic item needs to be confirmed. If the Confidence is greater than the semantic item's ConfirmThreshold, the event handler considers that the confidence is high enough that the semantic item does not need to be confirmed.

private void askCity_Closed(object sender, EventArgs e)
{
  if (askCity.RecognitionResult != null &&
      askCity.RecognitionResult.Semantics.ContainsKey("City"))
  {
    _city.Value = askCity.RecognitionResult.Semantics["City"].Value.ToString();
    if (askCity.RecognitionResult.Confidence <= _city.ConfirmThreshold)
    {
       _city.Update(_city.Value, SemanticItemState.NeedsConfirmation);
    }
    else
    {
      _city.Update(_city.Value, SemanticItemState.Confirmed);
     }
    _city.SpokenText = askCity.RecognitionResult.Text;
  }
}

The next example shows the TurnStarting event handler for confirmCity. Whether this activity executes depends on the state of the semantic item, which is controlled by the getCity_Closed event handler and the isRecoResultConfirmedIfElseActivity. If the semantic item's SemanticItemState is not Confirmed, this event handler executes and asks the user to confirm the recognized result.

private void confirmCity_TurnStarting(object sender, TurnStartingEventArgs e)
{
  this.confirmCity.MainPrompt.SetText(string.Format("You chose {0}", _city.Value));
  this.confirmCity.MainPrompt.AppendText("Is that correct?");
}

The following example is the code condition for the isRecoResultConfirmedIfElseActivity. It sets Result on ConditionalEventArgs to true if the state of the semantic item is Confirmed and to false, otherwise.

private void recoResultConfirmed(object sender, ConditionalEventArgs e)
{
  e.Result = (this._city.State == SemanticItemState.Confirmed);
}

Confirming or Denying a Response

The following example is the code condition for the isCityConfirmedIfElseActivity. If the user confirms that the recognized result is spoken, the example calls Accept on the semantic item, which changes the state of the semantic item to Confirmed. If the recognized result is not spoken, the example calls Deny on the semantic item, which changes the state of the semantic item to Empty and adds the semantic item to the DeniedValues collection.

private void cityConfirmed(object sender, ConditionalEventArgs e)
{
  e.Result = (this.confirmCity.RecognitionResult.Semantics.Value.ToString() == "Yes");
  if (e.Result == true)
  {
    _city.Accept();
  }
  else
  {
    _city.Deny();
  }
}