A user on the Expression Blend/SketchFlow forums recently asked a question about how to create a Quiz type of application in Silverlight without using much coding.  I created a simple example using a simple behavior to store the score of the quiz. Some of this behavior is redundant with new behaviors included with Blend 4, but the example should be illustrative if nothing else.

The behavior works by keeping static state in the ScoreKeeperAction class, which can be used to display the score. Each instance of a QuizQuestionBehavior that is attached to a RadioButton (the correct answer) will register its results with the ScoreKeeperAction class when invoked by determining if the RadioButton it is attached to is checked.

Each instance of the ScoreKeeperAction subscribes to changed events on the score, and updates its text whenever the score changes.

To use the behaviors, create a group of radiobuttons, and attach a QuizQuestionBehavior to the correct answer. Set the action’s trigger to a button that will submit the answer and the event to clicked. Also set the name of the Question in the behavior properties. An example of usage:

<Grid x:Name="LayoutRoot" >
		<RadioButton x:Name="CorrectAnswer" HorizontalAlignment="Left" Margin="45,47,0,0" VerticalAlignment="Top" Width="99" Content="Answer 1 (C)" GroupName="QuizGroup">
			<i:Interaction.Triggers>
				<i:EventTrigger SourceName="button" EventName="Click">
					<local:QuizQuestionBehavior QuestionName="Question 1"/>
				</i:EventTrigger>
			</i:Interaction.Triggers>
		</RadioButton>
        <RadioButton HorizontalAlignment="Left" Margin="45,68,0,0" VerticalAlignment="Top" Content="Answer 2" Width="99" GroupName="QuizGroup"/>
        <RadioButton HorizontalAlignment="Left" Margin="45,89,0,0" VerticalAlignment="Top" Content="Answer 3" Width="99" GroupName="QuizGroup"/>
		<RadioButton HorizontalAlignment="Left" Margin="45,110,0,0" VerticalAlignment="Top" Content="Answer 4" Width="99" GroupName="QuizGroup"/>
		<Button x:Name="button" Height="36" HorizontalAlignment="Left" Margin="45,135,0,0" VerticalAlignment="Top" Width="99" Content="Record Answer"/>
	</Grid>

To display the score, create a TextBlock and attach a ScoreKeeperAction, the user can set the text to be displayed in the behavior properties, SCORE is replaced with the number of correct answers and TOTAL is replaced with the total number of questions answered.

<TextBlock x:Name="ScoreBlock" Margin="9,9,8,8" Grid.Row="1" TextWrapping="Wrap">
	<i:Interaction.Triggers>
		<i:EventTrigger>
			<local:ScoreKeeperAction/>
		</i:EventTrigger>
	</i:Interaction.Triggers>
</TextBlock>

To display a summary create a TextBlock and attach a ScoreKeeperAction as well as setting the SummaryBox checkbox to true in the properties.

<TextBlock x:Name="textBlock" Margin="8,8,23,17" TextWrapping="Wrap" Text="Click update.">
	<i:Interaction.Triggers>
		<i:EventTrigger SourceName="textBlock">
			<local:ScoreKeeperAction SummaryBox="True"/>
		</i:EventTrigger>
	</i:Interaction.Triggers>
</TextBlock>

The code of the 2 Behaviors/Actions:

public class QuizQuestionBehavior : TriggerAction<RadioButton>
	{
		public static readonly DependencyProperty QuestionNameProperty = DependencyProperty.Register("QuestionName", typeof(string), typeof(QuizQuestionBehavior), new PropertyMetadata(Guid.NewGuid().ToString()));

    	public string QuestionName
        {
            get { return GetValue(QuestionNameProperty) as string; }
			set { SetValue(QuestionNameProperty, value); }
        }

		public QuizQuestionBehavior() {	}

		private bool answered = false;
		protected override void Invoke(object o)
		{
			if(!answered)
			{
				if(this.AssociatedObject.IsChecked == (bool?)true)
				{
					// Right
					ScoreKeeperAction.QuestionAnswered(this.QuestionName, true);
				}
				else
				{
					// Wrong
					ScoreKeeperAction.QuestionAnswered(this.QuestionName, false);
				}
			}
			answered = true;
		}
	}
public class ScoreKeeperAction : TriggerAction<TextBlock>
	{
		public static readonly DependencyProperty DisplayTextProperty = DependencyProperty.Register("DisplayText", typeof(string), typeof(ScoreKeeperAction), new PropertyMetadata("Answered SCORE/TOTAL questions correctly."));

		public string DisplayText
		{
			get { return GetValue(DisplayTextProperty) as string; }
			set { SetValue(DisplayTextProperty, value); }
		}

		public static readonly DependencyProperty SummaryBoxProperty = DependencyProperty.Register("SummaryBox", typeof(bool), typeof(ScoreKeeperAction), new PropertyMetadata(false));

		public bool SummaryBox
		{
			get { return (bool)GetValue(SummaryBoxProperty); }
			set { SetValue(SummaryBoxProperty, value); }
		}

		private static int questionsAnswered = 0;
		private static int QuestionsAnswered
		{
			get
			{
				return questionsAnswered;
			}
			set
			{
				if (questionsAnswered != value)
				{
					questionsAnswered = value;
					if (QuestionsAnsweredChanged != null)
					{
						QuestionsAnsweredChanged(null, new EventArgs());
					}
				}
			}
		}

		private static int correctQuestionsAnswered = 0;
		private static int CorrectQuestionsAnswered
		{
			get
			{
				return correctQuestionsAnswered;
			}
			set
			{
				if (correctQuestionsAnswered != value)
				{
					correctQuestionsAnswered = value;
					if (QuestionsAnsweredChanged != null)
					{
						QuestionsAnsweredChanged(null, new EventArgs());
					}
				}
			}
		}

		private static Dictionary<string, bool> questionResults = new Dictionary<string, bool>();

		public static void QuestionAnswered(string questionName, bool correct)
		{
			if (!questionResults.ContainsKey(questionName))
			{
				questionResults[questionName] = correct;
				QuestionsAnswered++;
				if (correct)
				{
					CorrectQuestionsAnswered++;
				}
			}
		}

		public static event EventHandler QuestionsAnsweredChanged;

		public ScoreKeeperAction()
		{
			QuestionsAnsweredChanged += new EventHandler(UpdateDisplay);
			UpdateDisplay();
		}

		private void UpdateDisplay(object sender, EventArgs e)
		{
			UpdateDisplay();
		}

		private void UpdateDisplay()
		{
			string text = this.DisplayText;
			if (String.IsNullOrEmpty(text))
			{
				text = "SCORE/TOTAL";
			}
			text = text.Replace("SCORE", CorrectQuestionsAnswered.ToString());
			text = text.Replace("TOTAL", QuestionsAnswered.ToString());
			if (this.SummaryBox)
			{
				// Add in summary below text.
				var sb = new StringBuilder();
				sb.AppendLine(text);
				foreach (var item in questionResults)
				{
					sb.AppendLine("Question " + item.Key + " answered " + (item.Value ? "correctly" : "incorrectly") + ".");
				}
				text = sb.ToString();
			}

			if (this.AssociatedObject != null)
			{
				this.AssociatedObject.Text = text;
			}
		}

		protected override void Invoke(object o)
		{
			UpdateDisplay();
		}
	}

The complete solution is available here: QuizApp.zip