MP3 does not trigger the Storyboard.Completed event - wpf

I am trying to use the Storyboard's Completed event to indicate when an audio file has finished playing.
However, it seems .Net behaves differently when playing mp3 and wav files, and the event is triggered only for WAV.
Here is a XAML and code that demonstrate the problem:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWind">
<Window.Resources>
<Storyboard x:Key="mp3StoryBoard" Completed="Storyboard_Completed">
<MediaTimeline Source="001.mp3" Storyboard.TargetName="mediaEl" >
</MediaTimeline>
</Storyboard>
<Storyboard x:Key="wavStoryBoard" Completed="Storyboard_Completed">
<MediaTimeline Source="001.wav" Storyboard.TargetName="mediaEl" >
</MediaTimeline>
</Storyboard>
</Window.Resources>
<Grid>
<MediaElement x:Name="mediaEl" Height="120" HorizontalAlignment="Left" Margin="120,94,0,0" VerticalAlignment="Top" Width="160" />
<Button Content="Play MP3" Height="23" HorizontalAlignment="Left" Margin="148,260,0,0" Name="btnMP3" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<Button Content="Play WAV" Height="23" HorizontalAlignment="Left" Margin="267,260,0,0" Name="btnWAV" VerticalAlignment="Top" Width="75" Click="btnWAV_Click" />
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = (Storyboard)this.mainWind.Resources["mp3StoryBoard"];
sb.Begin();
}
private void Storyboard_Completed(object sender, EventArgs e)
{
MessageBox.Show(" Storyboard finished");
}
private void btnWAV_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = (Storyboard)this.mainWind.Resources["wavStoryBoard"];
sb.Begin();
}
}
}
Will be glad if anyone has an idea for the reason for that and how to overcome it.

You don't have an attached event handler.
You need a
sb.Completed +=Storyboard_Completed;
before

The WPF MediaKit includes a MediaElement replacement, which may work better with mp3 files.

Related

How can I make the control can not be click while overlying?

I make an easy demo by WPF, here is the XAML:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown" Background="White">
<Border Height="100" Width="100" Background="Red" PreviewMouseLeftButtonDown="Border_PreviewMouseLeftButtonDown"></Border>
</Grid>
</Window>
And here is the code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Border");
}
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Grid");
}
}
}
I wanna do that if I press the border, it only activates the "Border" message box but not with the "Grid" message box also.
How can I do it? Would you please help me?
Thank you.
you can replace PreviewMouseLeftButtonDown with MouseDown.

wpf usercontrol resizing with thumb not firing DragDelta

I have created a Usercontrol that I would like to make resizable using the thumb control. I have added my control to a Canvas and when I click on the thumb control the only events that are fired are Dragend and DragStart (in that order) and DragDelta is not even firing. I have found someone with a similar problem Thumb inside an ItemsControl not firing DragDelta event but there is no way I can ask them if they found a solution.
This is the code :
<UserControl x:Class="test.ucChair"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="53" d:DesignWidth="93" RenderTransformOrigin="0.5,0.5" Background="Beige"
>
<Grid Name="grd" Margin="0,0,0,0">
<Rectangle x:Name="rectAngle" Margin="0,0,0,0" Stroke="Black" RenderTransformOrigin="0.5,0.5" Grid.ZIndex="1000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="53" /> <!-- Width="93" Height="53"-->
<TextBox x:Name="txtName" Text="OPEN" Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="True" IsReadOnlyCaretVisible="False" TextWrapping="Wrap" Width="93" KeyDown="txtName_KeyDown" FlowDirection="RightToLeft" BorderThickness="0" FontSize="14" Cursor="Hand" TextAlignment="Center"/>
<Thumb Name="thmbResize" DockPanel.Dock="Right" VerticalAlignment="Bottom" Height="15" Width="15"
DragDelta="OnResizeThumbDragDelta"
DragStarted="OnResizeThumbDragStarted"
DragCompleted="OnResizeThumbDragCompleted" HorizontalAlignment="Right">
</Thumb>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace test
{
/// <summary>
/// Interaction logic for ucChairLeft.xaml
/// </summary>
public partial class ucChair : UserControl
{
public ChairType AngleType;
//?? public int SectionID;
public ucChair()//ChairType CType)//?, int _SectionID)
{
InitializeComponent();
}
private void OnResizeThumbDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("DragEnd");
Mouse.Capture(null);
}
private void OnResizeThumbDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
System.Diagnostics.Debug.WriteLine("DragDelta");
}
private void OnResizeThumbDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
Mouse.Capture(this);
System.Diagnostics.Debug.WriteLine("DragStart");
}
}
}
<Window xmlns:test="clr-namespace:test" x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300">
<Canvas Width="300" Height="300" Background="LightBlue">
<test:ucChair Canvas.Left="50" Canvas.Top="100" Width="50" Height="50" Background="Yellow"/>
</Canvas>
</Window>
Any help greatly appreciated!

repeat button wpf not firing off click event

Hello community I have the following xaml.
<UserControl x:Class="Sample.SampleController"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="410" d:DesignWidth="324">
<UserControl.Resources>
<Style x:Key="buttonON" TargetType="RepeatButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid Width="80"
Height="80">
<Image Source="/Sample;component/icons/altitude_up_yellow.png"
Stretch="Fill" RenderOptions.BitmapScalingMode="Fant"/>
<ContentPresenter HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Name="DriveGrid" Background="#C9000000" Width="324" Height="410">
<RepeatButton HorizontalAlignment="Left" x:Name="button1" VerticalAlignment="Top" IsEnabled="True" Style="{StaticResource buttonON}" Margin="232,297,0,0" Delay="100" Interval="200" Width="80" Height="80"/>
</Grid>
</UserControl>
And the following Code Behind
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Controls.Primitives;
namespace Sample {
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class SampleController : UserControl {
public SampleController() {
InitializeComponent();
button1.Click += new RoutedEventHandler(UpBtn_Click);
}
void UpBtn_Click(object sender, RoutedEventArgs e) {
Console.WriteLine("Click");
}
}
}
My question, why doesn't the repeat button fire off continously when I press and hold?
Thank you for your help.
To sum up comments. Even though I am not able to reproduce the problem stated in the question, as the code above works fine for me, I have found very similar issue in RepeatButton fires event only once! article. There is no definite answer what's causing the issue but it may give some clues to what to try

RadioButton is checked, it's Checked event is call when run the app, and report exception

There are two RadioButtons and two Labels in .xaml, and check one RadioButton make the corresponding Label Enable. RadioButton1 is checked . Run the app, and the Checked Event is called automatically, but Label is null, so the app report exception.
I just use a variable to mark whether the window is first created. Whether there are other methods? I don't know why the app run the events after initialize all components, who can tell me?
MainWindow.xaml
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel>
<RadioButton
GroupName="Group"
IsChecked="True"
Content="RadioButton1"
x:Name="RadioButton1"
Checked="RadioButton1_Checked"
Unchecked="RadioButton1_Unchecked"/>
<RadioButton
GroupName="Group"
Content="RadioButton2"
x:Name="RadioButton2"
Checked="RadioButton2_Checked"
Unchecked="RadioButton2_Unchecked"/>
<Label
x:Name="Label1"
Content="Label1"/>
<Label
IsEnabled="False"
x:Name="Label2"
Content="Label2"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication7
{
/// <summary>
/// MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private bool isFirstRun;
public MainWindow()
{
isFirstRun = true;
InitializeComponent();
isFirstRun = false;
}
private void RadioButton1_Checked(object sender, RoutedEventArgs e)
{
if (isFirstRun)
return;
Label1.IsEnabled = true;
}
private void RadioButton2_Checked(object sender, RoutedEventArgs e)
{
Label1.IsEnabled = false;
}
private void RadioButton1_Unchecked(object sender, RoutedEventArgs e)
{
Label2.IsEnabled = true;
}
private void RadioButton2_Unchecked(object sender, RoutedEventArgs e)
{
Label2.IsEnabled = false;
}
}
}
I'm not sure if you have a specific reason for the EventHandlers, but if not you can do this logic directly in the Xaml using ElementName binding
Example:
<StackPanel>
<RadioButton x:Name="RadioButton1"
GroupName="Group"
IsChecked="True"
Content="RadioButton1" />
<RadioButton x:Name="RadioButton2"
GroupName="Group"
Content="RadioButton2" />
<Label x:Name="Label1"
IsEnabled="{Binding IsChecked, ElementName=RadioButton1}"
Content="Label1"/>
<Label x:Name="Label2"
IsEnabled="{Binding IsChecked, ElementName=RadioButton2}"
Content="Label2"/>
</StackPanel>
Why not simply remove the Ischecked="True" from the XAML and replace the isFirstRun = false variable being set after InitializeComponent(); with RadioButton1.IsChecked = true
this way you save having to define the isFirstRun variable.

WPF Databinding not calling !

I have UserControl which contains a TextBox and a Button control. The Button opens a FileDialog and the user selects the file. The selected file is transferred into the FileName property which is a dependency property. For some reason the TextBox is not binding to this property. Here is the code:
<UserControl x:Class="WPF3D.FileInputBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300" x:Name="root">
<Grid>
<StackPanel>
<TextBox Name="txtFile" Text="{Binding FileName, ElementName=root}" Width="300" Height="20" />
<Button Content="Select File" Width="100" Height="20" Click="SelectFile" />
</StackPanel>
</Grid>
</UserControl>
And here is the code for the UserControl.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.Windows.Markup;
namespace WPF3D
{
[ContentProperty("FileName")]
public partial class FileInputBox : UserControl
{
public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register("FileName",
typeof (String),
typeof (FileInputBox));
public event EventHandler<EventArgs> FileNameChanged;
public FileInputBox()
{
InitializeComponent();
txtFile.TextChanged += new TextChangedEventHandler(txtFile_TextChanged);
}
void txtFile_TextChanged(object sender, TextChangedEventArgs e)
{
e.Handled = true;
if(FileNameChanged != null)
{
FileNameChanged(this, EventArgs.Empty);
}
}
public string FileName
{
get { return (string) GetValue(FileNameProperty); }
set { SetValue(FileNameProperty,value);}
}
private void SelectFile(object sender, RoutedEventArgs e)
{
// select the file
var fileDialog = new OpenFileDialog();
fileDialog.ShowDialog();
this.FileName = fileDialog.FileName;
}
protected override void OnContentChanged(object oldContent, object newContent)
{
if(oldContent != null)
throw new InvalidOperationException("You can't change the content");
}
}
}
I think this is just a scoping issue as evident by this output in the debug window:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=root'. BindingExpression:Path=FileName; DataItem=null; target element is 'TextBox' (Name='txtFile'); target property is 'Text' (type 'String')
If you just change it to this, it works fine:
<UserControl x:Class="TestApp.FileInputBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Grid x:Name="_grid">
<StackPanel>
<TextBox Name="txtFile" Text="{Binding FileName}" Width="300" Height="20" />
<Button Content="Select File" Width="100" Height="20" Click="SelectFile" />
</StackPanel>
</Grid>
</UserControl>
And the important part of the code-behind:
public FileInputBox()
{
InitializeComponent();
txtFile.TextChanged += new TextChangedEventHandler(txtFile_TextChanged);
_grid.DataContext = this;
}
Note that setting the DataContext on the Grid rather than the UserControl is intentional. If you do it at the UserControl level it becomes possible for consumers of your control to break your bindings simply by changing the DataContext of your UserControl.

Resources