I have an application where I'm adding controls during runtime and want to attach EventTrigger(s) that are PlaySoundAction. In XAML this is easy, but with the need to generate controls on the fly and add these Triggers it becomes a bit more difficult.
I asked in a previous question and was able to get part way there and with recent testing I have come to a conclusion on what I can do to solve it, but was hoping there might be something I'm missing. I am able to get the EventTrigger working on a Button control, but not on a RegularPolygon and I'm unable to take an easy route on embedding a button inside of the RegularPolygon to achieve the results I want because it is not a ContentControl.
This is what I currently have this method for adding new RegularPolygons to a container (Canvas):
public RegularPolygon AddShape(Panel container)
{
RegularPolygon shape = new RegularPolygon();
// ShapeColors is a List<SolidColorBrush> that has been prepopulated
// _random is a Random() from .NET
shape.Fill = ShapeColors[_random.Next(0, ColorCount - 1)];
shape.Stretch = Stretch.Fill;
shape.PointCount = _random.Next(3, 6);
shape.UseLayoutRounding = false;
shape.Stroke = new SolidColorBrush(Colors.Black);
shape.Width = _random.Next(50, 150);
shape.Height = _random.Next(50, 150);
// UI_Tap is an arbitrary function for handling the Tap event
shape.Tap += UI_Tap;
System.Windows.Interactivity.EventTrigger trigger = new System.Windows.Interactivity.EventTrigger("Tap");
PlaySoundAction correct = new PlaySoundAction();
correct.Source = new Uri("/Sounds/Correct.mp3", UriKind.RelativeOrAbsolute);
correct.Volume = 1;
trigger.Actions.Add(correct);
//Button b = new Button();
//b.Content = "This is button B";
//System.Windows.Interactivity.Interaction.GetTriggers(b).Add(trigger);
//container.Children.Add(b);
// Comment this line out when uncommenting Button b block because Triggers
// can only be associated with one element
System.Windows.Interactivity.Interaction.GetTriggers(shape).Add(trigger);
Canvas.SetLeft(shape, _random.Next((int)(shape.Width / 2), (int)(container.Width - (shape.Width / 2))));
Canvas.SetTop(shape, _random.Next((int)(shape.Height / 2), (int)(container.Height - (shape.Height / 2))));
container.Children.Add(shape);
return shape;
}
I can see all my RegularPolygons appear on the screen. I have tested to make sure the path to the sound file works by having other test controls attempt to reference it at the listed location. No luck getting the EventTrigger with the PlaySoundAction to work. If I uncomment the lines around button b I can see the button added and Tap it to hear the sound play.
I can get a RegularPolygon to work with a PlaySoundAction EventTrigger in XAML as follows:
<es:RegularPolygon x:Name="haxx" Fill="#FFF4F4F5" Height="100" InnerRadius="1" Canvas.Left="125" PointCount="5" Stretch="Fill" Stroke="Black" Canvas.Top="187" UseLayoutRounding="False" Width="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<eim:PlaySoundAction Source="/Sounds/Correct.mp3"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</es:RegularPolygon>
My upcoming solution would be to create a custom control that will let me use the shape of the RegularPolygon with the functionality of the Button as I can get this to work from codebehind. Is there anything that I'm missing that is preventing me from having this EventTrigger work?
This was a case of not enough information in the question asked. The UI_Tap(...) method had a few goals:
What got was removing the object from the parent container and it did not immediately hit me that my object was going to be prevented from executing an EventTrigger associated with it. This is also why hardcoding in a RegularPolygon onto the MainPage.xaml worked as well as the Button above due to the fact that I never attempted to remove them inside of the Tap event handler.
I had some suggestions of tying the EventTrigger for the PlaySoundAction to the ManipulationStartedEvent because it occurs prior to the Tap event and this would work, but I'm going a more complex route of using XNA libraries to play a SoundEffect during an update loop. It involves creating an IApplicationLifetimeService and queuing sounds to play in FrameDispatchTimer_Tick event like this:
FrameworkDispatcher.Update has not been called and what to do about it