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

VideoViewerDemo视频播放器示例

clipboard.png

实现效果:

  1. 根据目录名选择里面播放文件,添加到列表。
  2. 点击播放列表,播放区自动播放对应文件
  3. 在播放列表上的鼠标提示中播放文件(无声的)

关注词:

  1. DirectoryInfo+ObservableCollection运用
  2. 数据绑定运用
  3. tooltip模板应用

实现步骤:
创建数据类MyVideo,包含标题及文件Uri.接收完整目录字符串及文件名

视频集类MyVideos
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后面垫有默认图片,没有播放时显示出来。
Souce绑定数据类的Uri属性

<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>

李志玮
22 声望34 粉丝

求索~~