[聚合文章] WPF:(5-1)程序样例VideoViewerDemo视频播放器示例

c# 2018-01-17 22 阅读

源项目地址:https://github.com/Microsoft/...
以下是把样例转换为简要说明,同时给出实际运行效果及关键代码剖析:

VideoViewerDemo视频播放器示例


功能有:
1 左侧播放列表鼠标的进入退出触发颜色变换、同时在工具提示里播放视频。
2 选择列表项变成蓝色,同时播放器播放选中视频

  • 视频集类

public class MyVideos : ObservableCollection<MyVideo>
存储指定路径目录,每次访问属性时,如目录存在且有文件,就进行更新把文件添加到播放列表中

public string Directory
{
    set
    {
        // Don't set path if directory is invalid
        if (!System.IO.Directory.Exists(value))
        {
            MessageBox.Show("No Such Directory");
        }

        _directory = new DirectoryInfo(value);

        Update();
    }
    get { return _directory.FullName; }
}
 private void Update()
{
    // Don't update if no directory to get files from
    if (_directory == null) return;

    // Remove all MyVideo objects from this collection
    Clear();

    // Create MyVideo objects
    foreach (var f in _directory.GetFiles("*.wmv"))
    {
        Add(new MyVideo(f.FullName, f.Name));
    }
}
  • Window窗口资源

实例化一个视频集类

<local:MyVideos Directory="../../media" x:Key="Vids" />

主屏幕播放区的数据模板,在grid后面垫有默认图片,没有播放时显示出来。

<DataTemplate x:Key="MainScreenTemplate">
    <Border BorderBrush="LimeGreen" BorderThickness="2"
            CornerRadius="3" Margin="15">
        <Grid>
            <!-- Background image if no video is playing. -->
            <Image Source="Images\Crystal.jpg" Stretch="Fill" />
            <!-- The video -->
            <!-- The Source property of the video is bound to the Source property of the current MyVideo object.-->
            <MediaElement Name="mainVideo" Stretch="Fill"
                          Source="{Binding Path=Source}" />
        </Grid>
    </Border>
</DataTemplate>

列表工具提示资源,声音被禁止。
X:Shared用于指定请求资源时创建实例的两种方式。
X:Shared = “true”(默认):表示所有请求都是共享同一个实例。一般不显示指定。
X:Shared = “false”:表示每次请求都创建一个新的实例。

<!-- Must be placed above listBoxTemplate -->
<ToolTip x:Key="PreviewScreen" x:Shared="True" Background="Transparent"
         Placement="Right" Name="previewToolTip">
    <Border BorderBrush="RoyalBlue" BorderThickness="2" CornerRadius="2">
        <MediaElement Source="{Binding Path=Source}"
                      Opacity="0.8" IsMuted="True" />
    </Border>
</ToolTip>

列表子项显示的数据模板,其中的资源对Dock容器样式进行设置,样式中鼠标悬浮触发显示上面的工具提示控件

<DataTemplate x:Key="ListBoxTemplate">
    <DataTemplate.Resources>
        <Style TargetType="DockPanel">
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="ToolTipService.ShowDuration" Value="80000" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="ToolTip" Value="{StaticResource PreviewScreen}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataTemplate.Resources>
    <DockPanel Height="70" Width="160">
        <Border Margin="4,5,0,0" Height="50" Width="50">
            <Image Source="Images\Preview.png" />
        </Border>
        <TextBlock Text="{Binding Path=VideoTitle}" VerticalAlignment="Center"
                   TextBlock.TextTrimming="CharacterEllipsis" Margin="5,5,0,5"
                   Foreground="Black" FontSize="12" FontFamily="Comic Sans MS" />
    </DockPanel>
</DataTemplate>

对每个列表子项显示的样式资源,其的每个子项的内容模板进行了修饰,两个方框进行鼠标进入及退出时背景色变化动画触发。每个子项的样式又进行鼠标选中时的方框背景色变化动画触发。

<Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem">
    <Setter Property="Margin" Value="10,10,10,0" />
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="ListBoxItem">
            <Grid>
                <Rectangle x:Name="GelBackground" RadiusX="9" RadiusY="9"
                           Opacity="1" Fill="{TemplateBinding Background}"
                           Stroke="#66ffffff" StrokeThickness="1" />
                <Rectangle x:Name="GelShine" RadiusX="6" RadiusY="6"
                           Opacity="1" Margin="2,2,2,0" VerticalAlignment="top"
                           Stroke="transparent" Height="15">
                    <Rectangle.Fill>
                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                            <GradientBrush.GradientStops>
                                <GradientStopCollection>
                                    <GradientStop Color="#ccffffff" Offset="0" />
                                    <GradientStop Color="transparent" Offset="1" />
                                </GradientStopCollection>
                            </GradientBrush.GradientStops>
                        </LinearGradientBrush>
                    </Rectangle.Fill>
                </Rectangle>
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
            </Grid>
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="Mouse.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard TargetName="GelBackground"
                                        TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                <ColorAnimation To="LimeGreen" Duration="0:0:0.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard TargetName="GelBackground"
                                        TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                <ColorAnimation Duration="0:0:0.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
    </Setter>
    <Style.Triggers>
    <Trigger Property="IsSelected" Value="true">
        <Setter Property="Background" Value="RoyalBlue" />
    </Trigger>
    </Style.Triggers>
    </Style>
  • 前台播放列表及播放器xaml代码

其中IsSynchronizedWithCurrentItem="True"必须设置,意思为同步当前选择项进行处理。就是当选中一个播放项,同一个绑定源的控件ContentControl实例化选中的视频自动到MediaElement进行播放,可谓关键代码。

<!-- 1) The ListBox and ContentControl bind to the same source. -->
<!-- 2) IsSynchronizedWithCurrentItem set to true. -->
<!-- With the above 2 conditions satisfied, once the DataTemplates are in place,   the ContentControl will display the content of the selected list item.-->
<DockPanel>
    <ListBox DockPanel.Dock="Left" Width="200" BorderThickness="0"
             ItemsSource="{Binding Source={StaticResource Vids}}"
             IsSynchronizedWithCurrentItem="True"
             ItemTemplate="{StaticResource ListBoxTemplate}"
             Background="Transparent" />
    <ContentControl Content="{Binding Source={StaticResource Vids}}"
                    ContentTemplate="{StaticResource MainScreenTemplate}" />
</DockPanel>

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。