WPF设置软件界面背景为MediaElement并播放视频

摘要:
我们首先来看看前台样式的设计:在这里我们用到了VisualBrush这个画刷,然后再在VisualBrush的Visual中添加我们自定义的Style,这个是一个非常重要的画刷,如果我们对WPF的继承关系清楚的话,我们会发现几乎所有的控件都是从Visual这个顶级的基类继承过来的,所以几乎所有的Control都能够作为VisualBrush的Visual,所以Grid的Background属性是十分丰富的,这里我们定义了一个BackgroundPlayer的自定义控件,并且更改了其控件模板。

在我们的常见的软件界面设计中我们经常会设置软件的背景为SolidColorBrush或者LinerColorBrush、RadialGradientBrush等一系列的颜色画刷为背景,有时我们也会使用ImageBrush添加图片来作为界面的背景,另外常用的还有DrawingBrush以及今天需要进行总结的VisualBrush,这些我们都是比较容易实现的,那么我们如果想将软件的界面设计成一个动画或者干脆播放一段视频作为背景,这个对于整个软件的效果又是一个巨大的提升。

首先我们来看看background属性,MSDN上的解释是:获取或设置用于填充控件Control的边框之间的区域的Brush。它的类型是:Type:System.Windows.Media.Brush,所以我们能够使用具有Brush属性的控件或者属性来作为背景来填充它。

我们首先来看看前台样式的设计:

<Window x: 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ui="clr-namespace:X.UI;assembly=X.UI"   
        xmlns:local="clr-namespace:TestBackGroundWorker"
        Title="MainWindow"   Width="1000">
    <Window.Resources>
        <Style TargetType="local:BackgroundPlayer">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:BackgroundPlayer">
                        <MediaElement x:Name="Media" Stretch="Fill"></MediaElement>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.Background>
            <VisualBrush>
                <VisualBrush.Visual>                    
                    <local:BackgroundPlayer Source="~/Images/bg.avi"></local:BackgroundPlayer>
                </VisualBrush.Visual>
            </VisualBrush>
        </Grid.Background>
    </Grid>
</Window>

在这里我们用到了VisualBrush这个画刷,然后再在VisualBrush的Visual中添加我们自定义的Style,这个是一个非常重要的画刷,如果我们对WPF的继承关系清楚的话,我们会发现几乎所有的控件都是从Visual这个顶级的基类继承过来的,所以几乎所有的Control都能够作为VisualBrush的Visual,所以Grid的Background属性是十分丰富的,这里我们定义了一个BackgroundPlayer的自定义控件,并且更改了其控件模板。

那么我们再重点看一下这个自定义控件的后台是如何进行定义的:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows;
usingSystem.Windows.Controls;

namespaceTestBackGroundWorker
{
    public classBackgroundPlayer : System.Windows.Controls.Control
    {
        staticBackgroundPlayer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BackgroundPlayer), new FrameworkPropertyMetadata(typeof(BackgroundPlayer)));
        }

        public stringSource
        {
            get { return (string)GetValue(SourceProperty); }
            set{ SetValue(SourceProperty, value); }
        }
      
        public static readonly DependencyProperty SourceProperty =DependencyProperty.Register("Source", typeof(string), typeof(BackgroundPlayer), new FrameworkPropertyMetadata("", (a, b) =>{
                BackgroundPlayer bp = a asBackgroundPlayer;
                if (bp.Player != null)
                {
                    bp.Player.Source = new Uri(b.NewValue.ToString().Replace("~", AppDomain.CurrentDomain.BaseDirectory), UriKind.RelativeOrAbsolute);
                }               
            }));

        privateMediaElement _player;

        publicMediaElement Player
        {
            get { return_player; }
            set { _player =value; }
        }

        public override voidOnApplyTemplate()
        {
            Player = GetTemplateChild("Media") asMediaElement;
            if (null ==Player)
                throw new ArgumentNullException("Media");

            Player.LoadedBehavior =MediaState.Manual;
            Player.MediaEnded +=Player_MediaEnded;
            Player.MediaOpened +=Player_MediaOpened;
            Player.MediaFailed +=Player_MediaFailed;
            Player.Loaded +=Player_Loaded;
            if (!string.IsNullOrEmpty(Source))
            {
                Player.Source = new Uri(Source.Replace("~", AppDomain.CurrentDomain.BaseDirectory), UriKind.RelativeOrAbsolute);
                Player.Play();
            }
            base.OnApplyTemplate();
        }

        void Player_Loaded(objectsender, RoutedEventArgs e)
        {
        }

        void Player_MediaFailed(objectsender, ExceptionRoutedEventArgs e)
        {
        }

        void Player_MediaOpened(objectsender, RoutedEventArgs e)
        {
            //Player.Play();
}

        void Player_MediaEnded(objectsender, RoutedEventArgs e)
        {
            Player.Position = TimeSpan.FromMilliseconds(1);
            Player.Play();
        }

    }
}

这里我们的自定义控件是从System.Windows.Controls.Control这里继承过来的,我们看一下相关的代码,然后做进一步的分析。首先我们必须为当前的类添加一个默认的静态构造函数,这个是非常重要的,它会更改默认的Control的样式。

static BackgroundPlayer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BackgroundPlayer), new FrameworkPropertyMetadata(typeof(BackgroundPlayer)));
        }

接下来我们需要为自定义控件定义一些默认的依赖项属性,首先第一个是:Source属性,既然我们将Control的属性定义为MediaElement,那么我们一定要为这个MediaElement设置相关的属性,这里我们为这个Source属性定义了一个当属性变化时的回调函数,这个在xaml中第一次为Source属性赋值时就会触发该回调函数,所以我们经常可以利用该回调函数来做一些操作,这个回调函数是非常有用的。

另外我们还需要为MediaElement设置一些常见的属性,比如说当前片源放完成后会后续进行什么操作等。

这里我们是通过重载基类的OnApplyTemplate方法来进行相关的操作的,我们在了解WPF时必须懂得,去重载这些常见的虚方法来完成我们的操作。当然这也需要我们不断去积累。

我们来看看OnApplyTemplate这个虚方法是为了完成什么样的操作,通过重写OnApplyTemplate()后就可以通过GetTemplateChild方法获取模板里的子控件了,但是OnApplyTemplate的执行顺序有问题,当类的构造函数执行后,并不是立即执行OnApplyTemplate方法,而是延迟了一定的时间,而且如果这个自定义的控件在放到应用的项目中时如果Visibility为隐藏的话,更是不会执行OnApplyTemplate方法了,这点需要我们去留心,在我们的程序中也是通过重写OnApplyTemplate方法来获取MediaElement对象,从而为其添加事件,这是一种非常有效果的方式。

最后贴出相应的截图看看动画的效果(星空风格图)

WPF设置软件界面背景为MediaElement并播放视频第1张 完整的视频是一副移动的画面,这里只是截出了很少的照片,正常播放时整个都面都动,上面的文章只是简约去分析,仅供参考。

免责声明:文章转载自《WPF设置软件界面背景为MediaElement并播放视频》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用 GitHub 开源项目申请 IntelliJ LicenseiOS 动画笔记 (二)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#(4):XML序列化

一、使用 System.Xml.Serialization类 1、定义元数据 引入System.Xml.Serialization命名空间。 XML序列化常用属性: XmlRoot XmlType XmlText XmlEnum [Serializable] [XmlRoot] public class Product { public int...

WPF中TreeView控件的使用案例

WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用。我这个demo主要是在wpf中使用TreeView控件实现图片查看功能,简单的Grid布局、TreeView控件添加图标、TreeView控件的一些事件、显示统计、还有就是读取文件操作。 效果图:...

WPF学习笔记:ComboBox的数据绑定

UI <UserControl x: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"...

Angular2中实现基于TypeScript的对象合并方法:extend()

TypeScript里面没有现成的合并对象的方法,这里借鉴jQuery里的$.extend()方法。写了一个TypeScript的对象合并方法,使用方法和jQuery一样。 部分代码和jQuery代码略有不同,主要是判断元素是否为数组和纯对象的部分。jQuery中有方法可直接判断元素是否为数组($.isArray())和对象($.isPlainObject...

WPF-带有GridView的ListView样式

ListView是展示数据的常用控件,这里简单对带有GridView的ListView样式进行设置。 <Style TargetType="{x:Type ListViewItem}"> <Style.Triggers> <Trigger Property="IsSel...

WPF 多项选择下拉菜单

背景 项目中有一个多项选择筛选的功能, 由于筛选条件太多, 用户又习惯在平板上进行操作, 所以要求我们把checkbox 放到一个combobox里面, 然后checkbox的选项要在combobox里面显示出来, 再加一个全选功能. 喏, 就是这种效果. 实现     首先, 实现思路是: 1. 自定义一个用户控件 2.添加一个combobox 3...