c# WPF設置軟件界面背景為MediaElement並播放視頻

    在我們的常見的軟件界面設計中我們經常會設置軟件的背景為SolidColorBrush或者LinerColorBrush、RadialGradientBrush 等一系列的顏色畫刷為背景,有時我們也會使用ImageBrush添加圖片來作為界面的背景,另外常用的還有DrawingBrush以及今天需要進行總結的VisualBrush,這些我們都是比較容易實現的,那麼我們如果想將軟件的界面設計成一個動畫或者幹脆播放一段視頻作為背景,這個對於整個軟件的效果又是一個巨大的提升。

    首先我們來看看background屬性,MSDN上的解釋是:獲取或設置用於填充控件Control的邊框之間的區域的 Brush。它的類型是:Type: System.Windows.Media.Brush,所以我們能夠使用具有Brush屬性的控件或者屬性來作為背景來填充它。

    我們首先來看看前臺樣式的設計: 

<Window x:Class="TestBackGroundWorker.MainWindow"
        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" Height="681" 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的自定義控件,並且更改瞭其控件模板。

     那麼我們再重點看一下這個自定義控件的後臺是如何進行定義的:      

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace TestBackGroundWorker
{
  public class BackgroundPlayer : System.Windows.Controls.Control
  {
    static BackgroundPlayer()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(BackgroundPlayer), new FrameworkPropertyMetadata(typeof(BackgroundPlayer)));
    }

    public string Source
    {
      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 as BackgroundPlayer;
        if (bp.Player != null)
        {
          bp.Player.Source = new Uri(b.NewValue.ToString().Replace("~", AppDomain.CurrentDomain.BaseDirectory), UriKind.RelativeOrAbsolute);
        }        
      }));

    private MediaElement _player;

    public MediaElement Player
    {
      get { return _player; }
      set { _player = value; }
    }

    public override void OnApplyTemplate()
    {
      Player = GetTemplateChild("Media") as MediaElement;
      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(object sender, RoutedEventArgs e)
    {
    }

    void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
    {
    }

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

    void Player_MediaEnded(object sender, 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對象,從而為其添加事件,這是一種非常有效果的方式。

      最後貼出相應的截圖看看動畫的效果(星空風格圖)

以上就是c# WPF設置軟件界面背景為MediaElement並播放視頻的詳細內容,更多關於c# WPF設置軟件界面背景為MediaElement的資料請關註WalkonNet其它相關文章!

推薦閱讀: