1. 程式人生 > >相對完善的 WPF 自定義 MessageBox

相對完善的 WPF 自定義 MessageBox

基於WPF的自定義 MessageBox.

眾所周知WPF介面美觀.大多數WPF元素都可以簡單的修改其樣式,從而達到程式的風格統一.可是當你不得不彈出一個訊息框通知使用者訊息時(雖然很不建議在程式中頻繁的彈框,恩,我說的是不得不...).那個預設的System.Windows.MessageBox 就顯得太醜陋,太不搭調了.因此想到怎麼搞一個新的MessageBox替換掉預設的.有童鞋說WPF擴充套件包中提供了新的MessageBox,那也只是把MessageBox的樣式從XP提高到了Win7樣式而已,大多還是與完全自定義樣式的WPF程式不搭調.貌似它也提供了修改樣式的介面,不過沒多少人會使用吧.也有人說,我隨便自定義一個控制元件,或者隨便在XAML中放一個POPUP 一個BORDER什麼的 也可以模擬MessageBox的效果. 你累不?

屁話不多說了,正題開始...

/***********************************************萬能分隔線,無視上面的一切吧**************************************************************/

一:首先自定義核心的東東.訊息框本身也是個視窗.那麼我麼就需要重新繼承一個Window類,這裡起名 MessageBoxModule 

class MessageBoxModule : Window{        static MessageBoxModule()        {        // 指定自定義 控制元件 搜尋的 樣式模板型別            DefaultStyleKeyProperty.OverrideMetadata( 
typeof( MessageBoxModule ), new FrameworkPropertyMetadata( typeof( MessageBoxModule ) ) );        }        public MessageBoxModule()        {            try            {                this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                this.AllowsTransparency = true
;                this.WindowStyle = System.Windows.WindowStyle.None;                this.ShowInTaskbar = false;                this.Topmost = true;                this.MouseLeftButtonDown += ( o, e ) =>                {                    this.DragMove();                };                // 為MessageBoxModule 掛載資原始檔,為了使用資源中的一些 樣式定義. 注意 Uri中路徑的寫法.                Resources.Source = new Uri( @"/Vito.Csharp.Wpf.Controls;component/Themes/Generic.xaml", UriKind.Relative );                if ( Resources.Contains( "MessageBoxButtonStyle" ) )                {                    MessageBoxModule.SetDefaultCtorButtonStyle( Resources["MessageBoxButtonStyle"] as Style );                }            }            catch { }        }}

 /Themes/Generic.xaml 樣式模板我就不多說了.這裡主要介紹些Messagebox的封裝思路.

上面構造完,我們就得到了一個看起來類似訊息框的視窗了. 訊息框中需要有視窗標題,訊息框顯示內容,和訊息框的響應按鈕.接下來我們逐步完善此類.

下面我們在類中加入些屬性.

        public new string Title        {            get { return (string)GetValue( TitleProperty ); }            set { SetValue( TitleProperty, value ); }        }        public string Message        {            get { return (string)GetValue( MessageProperty ); }            set { SetValue( MessageProperty, value ); }        }        public Brush TitleForeground        {            get { return (Brush)GetValue( TitleForegroundProperty ); }            set { SetValue( TitleForegroundProperty, value ); }        }      // 自定義響應按鈕的集合        public IList<Button> CtrlButtonCollection        {            get { return (IList<Button>)GetValue( CtrlButtonCollectionProperty ); }            set { SetValue( CtrlButtonCollectionProperty, value ); }        }        public new static readonly DependencyProperty TitleProperty =    DependencyProperty.Register( "Title", typeof( string ), typeof( MessageBoxModule ), new PropertyMetadata( "標題" ) );        public static readonly DependencyProperty MessageProperty =    DependencyProperty.Register( "Message", typeof( string ), typeof( MessageBoxModule ), new PropertyMetadata( "" ) );        public static readonly DependencyProperty TitleForegroundProperty =    DependencyProperty.Register( "TitleForeground", typeof( Brush ), typeof( MessageBoxModule ), new PropertyMetadata( DefaultTitleForeground ) );        public static readonly DependencyProperty CtrlButtonCollectionProperty =    DependencyProperty.Register( "CtrlButtonCollection", typeof( IList<Button> ), typeof( MessageBoxModule ), new PropertyMetadata( new List<Button>() /*{ new Button() { Content = "確定" }, new Button() { Content = "取消" } }*/ ) );

其中 CtrlButtonCollection 屬性為本訊息框的特色了,他是一組可控的響應按鈕集合.當你的訊息框中不想使用預設提供的(eg: MessageBoxButton.OKCancel,MessageBoxButton.YesNo 等等)按鈕時,可以使用該集合,我們後面再說.

MessageBoxModule 類作為訊息框 那麼一定要有Show方法唄,那麼我們來提供一組MessageBoxModule.Show方法,為了看起來很牛x 我們直接Copy System.Windows.MessageBox的部分Show方法來重寫.

public static MessageBoxResult Show( string messageBoxText ){ // ....}public static MessageBoxResult Show( string messageBoxText, string caption ){ // .......}public static MessageBoxResult Show( string messageBoxText, string caption, MessageBoxButton button ){ //  .......}public static MessageBoxResult Show( Window owner, string messageBoxText ){ //...}public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, MessageBoxButton button ){ // ......}//特色public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, IList<MessageBoxButtonInfo> ctrlButtons ){ // ..}

為了相容同志們曾經的MessageBox.Show方法,我們這裡定義的Show方法都和預設訊息框的一樣.多數情況下我們可能不需要自定義訊息框按鈕的文字樣式等資訊,所以我們提供了對

預設的 MessageBoxButton 列舉的支援. 這樣我們可以只需要再想要替換新訊息框的專案中加入自己的名稱空間引用就可以了. 熟悉預設MessageBox的童鞋可能發現了上面的Show過載中沒有提供對 MessageBoxImage 列舉的支援.是的,我故意沒有加入對圖片的支援. 因為我覺得加入個圖片很有可能破壞我們整個應用程式的風格.而且其實這個圖片的提示也沒有那麼重要.完全是我的個人見解.如果您需要MessageBoxImage 那麼您可以來完善這個.

大致思路: 因為MessageBoxImage也是列舉,那麼我們需要在我們的控制元件庫中加入預設的圖片對應.不過,我建議不要使用圖片資源,該用Path,路徑來替代圖片.因為如果使用某些個圖片作為預設資源,由於圖片無法動態修改前景 背景顏色,所以預設實用性不大,而路徑可以完全支援 大小,顏色的變換.(鄙人完全不建議在WPF的程式中使用任何圖片!應用程式背景,按鈕背景,特效之類的,完全可以使用WPF強大的顏色渲染和路徑支援來替代.) 根據傳入的MessageBoxImage值動態Binding指定的圖片(路徑)就行了.

上面前四個Show都是對後面的呼叫.所以我們大概看一下後2個SHow方法的實現.

public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, MessageBoxButton button )        {            var mbox = new MessageBoxModule();            mbox.Message = messageBoxText;            mbox.Title = caption;            mbox.Owner = owner;        // 這個方法是檢測本次彈出的訊息框是否使用了自定義的顏色配置,而不是使用預設提供的顏色配置.後面再說,這裡無視.            IsUseCustomInfoDefine( ref mbox );            if ( owner != null )            {                mbox.WindowStartupLocation = WindowStartupLocation.CenterOwner;            }        //這裡的分支語句提供了傳入MessageBoxButton列舉的具體響應實現. 其中CreateCtrlButton_ResultTrue,CreateCtrlButton_ResultFalse        // 等方法是建立一個按鈕 並默認了按鈕的響應 和Show方法完成後返回的結果. // 後面在看.switch ( button )            {                case MessageBoxButton.OKCancel:                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultTrue( mbox, "確定" ) );                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultFalse( mbox, "取消" ) );                    break;                //break;                case MessageBoxButton.YesNo:                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultTrue( mbox, "" ) );                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultFalse( mbox, "" ) );                    break;                case MessageBoxButton.YesNoCancel:                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultTrue( mbox, "" ) );                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultFalse( mbox, "" ) );                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultFalse( mbox, "取消" ) );                    break;                case MessageBoxButton.OK:                default:                    mbox.CtrlButtonCollection.Add( CreateCtrlButton_ResultTrue( mbox, "確定" ) );                    break;            }            var result = mbox.ShowDialog();  // 本行程式碼是訊息框彈出的核心.ShowDialog方法會開啟一個模態對話方塊.等待返回結果.這裡的結果不是MessageBoxResult列舉而是可空型別的布林值(bool?) true對應著MessageBoxResult.Yes ,MessageBoxResult.OK的值.false對應著MessageBoxResult.Cancel,MessageBoxResult.No 的值.      // 瞭解這些我們就可以對ShowDialog方法返回值做MessageBoxResult轉換了.switch ( button )            {                //break;                case MessageBoxButton.OKCancel:                    {                        return result == true ? MessageBoxResult.OK                            : result == false ? MessageBoxResult.Cancel :                            MessageBoxResult.None;                    }                //break;                case MessageBoxButton.YesNo:                    {                        return result == true ? MessageBoxResult.Yes : MessageBoxResult.No;                    }                //break;                case MessageBoxButton.YesNoCancel:                    {                        return result == true ? MessageBoxResult.Yes                            : result == false ? MessageBoxResult.No :                            MessageBoxResult.Cancel;                    }                case MessageBoxButton.OK:                default:                    {                        return result == true ? MessageBoxResult.OK : MessageBoxResult.None;                    }            }        }
        private static Button CreateCtrlButton_ResultTrue( MessageBoxModule mbox, string content )        {            return CreateCtrlButton( content, new RoutedEventHandler( ( o, e ) =>            {                try                {   // 這裡的DialogResult = true 賦值,表示著 Show方法的返回值可能為 Yes OK的值.             // 所以這個方法支援了MessageBoxButton.OKCancel,MessageBoxButton.YesNo,MessageBoxButton.OK ,MessageBoxButton.YesNoCancel            // 列舉中的Yes Ok部分的支援. 同理另外2個方法類似.                    mbox.DialogResult = true;                    mbox.Close();                }                catch { }            } ) );        }        private static Button CreateCtrlButton_ResultFalse( MessageBoxModule mbox, string content )        {            return CreateCtrlButton( content, new RoutedEventHandler( ( o, e ) =>            {                try                {                    mbox.DialogResult = false;                    mbox.Close();                }                catch { }            } ) );        }        private static Button CreateCtrlButton_ResultNull( MessageBoxModule mbox, string content )        {            return CreateCtrlButton( content, new RoutedEventHandler( ( o, e ) =>            {                try                {                    mbox.DialogResult = null;                    mbox.Close();                }                catch { }            } ) );        }

到此,我們就完成了預設提供的Show方法的實現了.下面來看自定義的部分. 首先來看一下 MessageBoxButtonInfo這個類,

    /// <summary>    /// Vito.Csharp.Wpf.Controls.MessageBoxModule 元件中 MessageBoxButton 的自定義設定資訊.    /// </summary>    public class MessageBoxButtonInfo    {        #region fields        private string _contentText = "";        private MessageBoxResult _result = MessageBoxResult.OK;        private Action<object> _action = null;        #endregion // fields        #region ctor        /// <summary>        /// 初始化 MIV.Bus.IEMS.MessageBox 自定義按鈕的基本資訊.        /// </summary>        /// <param name="contentText">按鈕的文字內容</param>        /// <param name="result">按鈕響應的返回結果</param>        /// <param name="action">按鈕的響應動作</param>        public MessageBoxButtonInfo( string contentText, MessageBoxResult result, Action<object> action )        {            this._contentText = contentText;            this._result = result;            if ( null != action )            {                this._action = action;            }            else            {                this._action = new Action<object>( ( o ) =>                {                } );            }        }        #endregion // ctor        #region Readonly Properties        /// <summary>        /// 獲取 MIV.Bus.IEMS.MessageBox 按鈕的文字內容.        /// </summary>        public string ContentText        {            get { return _contentText; }        }        /// <summary>        /// 獲取 MIV.Bus.IEMS.MessageBox 按鈕響應的返回結果.        /// </summary>        public MessageBoxResult Result        {            get { return _result; }        }        /// <summary>        /// 獲取 MIV.Bus.IEMS.MessageBox 按鈕的響應動作.        /// </summary>        public Action<object> Action        {            get { return _action; }        }        #endregion // Readonly Properties    }

這個類中包含了一些自定義按鈕需要的引數.

ContentText 表示著自定義按鈕中的顯示文字(eg:例如 我想要顯示"確認""取消""是""否"之類的文字,我要顯示"不了,謝謝"字樣的類似取消功能的按鈕,那麼這個引數就是攜帶該值的).

Result 指示了本個自定義的按鈕響應後文本框返回什麼值(這個是之前版本的遺留,現在沒啥用處了.暫時無視.)

Action 表示本個按鈕的響應方法. 需要在按了按鈕之後做什麼,那就傳遞給它吧.

下面看詳細的Show方法實現.

        public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, IList<MessageBoxButtonInfo> ctrlButtons )        {            var mbox = new MessageBoxModule();            mbox.Message = messageBoxText;            mbox.Title = caption;            mbox.Owner = owner;            IsUseCustomInfoDefine( ref mbox ); // 同上,檢測是否使用自定義主題顏色的配置.            if ( owner != null )            {                mbox.WindowStartupLocation = WindowStartupLocation.CenterOwner;            }            if ( null != ctrlButtons && ctrlButtons.Count > 0 )            {                foreach ( var btnInfo in ctrlButtons )                {                    switch ( btnInfo.Result )                    {                        case MessageBoxResult.Cancel:                        case MessageBoxResult.No:                            {                                var btn = CreateCtrlButton_ResultFalse( mbox, btnInfo.ContentText );                                btn.Command = new MessageBoxCommand( btnInfo.Action );  // 為按鈕關聯響應動作. 這裡我把Action封裝為了命令.MessageBoxCommand為自定義的命令.                                mbox.CtrlButtonCollection.Add( btn );                            }                            break;                        case MessageBoxResult.None:                            {                                var btn = CreateCtrlButton_ResultNull( mbox, btnInfo.ContentText );                                btn.Command = new MessageBoxCommand( btnInfo.Action );                                mbox.CtrlButtonCollection.Add( btn );                            }                            break;                        case MessageBoxResult.OK:                        case MessageBoxResult.Yes:                        default:                            {                                var btn = CreateCtrlButton_ResultTrue( mbox, btnInfo.ContentText );                                btn.Command = new MessageBoxCommand( btnInfo.Action );                                mbox.CtrlButtonCollection.Add( btn );                            }                            break;                    }                }                var result = mbox.ShowDialog(); //同上一個Show方法.這裡呼叫會顯示一個模態視窗.                return MessageBoxResult.None;//為啥我說MessageBoxButtonInfo類中的Result沒用了,因為這裡我始終返回None了.返回結果的目的是為了根據不同的結果做不同的處理,而這裡的Action已經對其作出了響應.所以返回結果的用處不大.            }            else            {                return Show( owner, messageBoxText, caption, MessageBoxButton.OK );            }        }

MessageBoxCommand 實現:

    /// <summary>    /// MIV.Bus.IEMS.MessageBoxModule 元件的自定義事件    /// </summary>    public class MessageBoxCommand : ICommand    {        #region Private Fields        private readonly Action<object> _command;        private readonly Func<object, bool> _canExecute;        #endregion        #region Constructor        public MessageBoxCommand( Action<object> command, Func<object, bool> canExecute = null )        {            if ( command == null )                throw new ArgumentNullException( "command" );            _canExecute = canExecute;            _command = command;        }        #endregion        #region ICommand Members        public void Execute( object parameter )        {            _command( parameter );        }        public bool CanExecute( object parameter )        {            if ( _canExecute == null )                return true;            return _canExecute( parameter );        }        public event EventHandler CanExecuteChanged        {            add { CommandManager.RequerySuggested += value; }            remove { CommandManager.RequerySuggested -= value; }        }        #endregion    }

自定義命令.網上一堆文字,這裡不做解釋了.

到這裡,基本的Messagebox就已經完成了.我們可以使用 MessageBoxModule.Show 方法來實現訊息框. 當我們敲出MessageBoxModule.的時候,我們會發現,次奧!MessageBoxModule下面彈出的東西怎麼這麼多? 好亂啊,各種靜態方法,DependencyProperty 之類的.而預設的MessageBox.彈出來的只有區區 Show,ReferenceEquals ,Equals三個方法.一眼就看到了Show.

再者,我們跳轉到MessageBox類時可以看到 這個類是"public sealed class MessageBox" 是密封的,並且也不是繼承Window的類.那麼他是怎麼實現的呢?很簡單,包裝一下而已. 隱藏掉了真正的視窗,留給我們使用的只是一個功能類而已.這樣使用者就不可以在介面中加入MessageBox.也無法搞其他的東西了.吐槽一下MS...

我們也來封裝一下我們自己的MessageBox類.如下:

    /// <summary>    /// 顯示訊息框.    /// </summary>    public sealed class MessageBox    {        #region ctors        static MessageBox()        {        }        private MessageBox()        {        }        #endregion // ctors        #region custom settings        /// <summary>        /// 設定 MIV.Bus.IEMS.MessageBox 的按鈕樣式.        /// </summary>        /// <param name="buttonStyle"></param>        public static void SetDefaultCtorButtonStyle( Style buttonStyle )        {            MessageBoxModule.SetDefaultCtorButtonStyle( buttonStyle );        }        /// <summary>        /// 設定 MIV.Bus.IEMS.MessageBox 的一些自定義資訊.        /// </summary>        /// <param name="mbCustomIf">MIV.Bus.IEMS.MessageBox 自定義資訊結構</param>        public static void SetMessageBoxCustomDefine( MessageBoxCustomInfo mbCustomIf )        {            MessageBoxModule.SetMessageBoxCustomDefine( mbCustomIf );        }        public static void ResetMessageBoxCustomDefine()        {            MessageBoxModule.ResetMessageBoxCustomDefine();        }        #endregion // custom settings        #region Show functions        /// <summary>        /// 顯示一個訊息框,該訊息框包含訊息並返回結果。        /// </summary>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <returns>一個 System.Windows.MessageBoxResult 值,用於指定使用者單擊了哪個訊息框按鈕。</returns>        public static MessageBoxResult Show( string messageBoxText )        {            return MessageBoxModule.Show( messageBoxText );        }        /// <summary>        /// 顯示一個訊息框,該訊息框包含訊息和標題欄標題,並且返回結果。        /// </summary>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <param name="caption"> 一個 System.String,用於指定要顯示的標題欄標題。</param>        /// <returns>一個 System.Windows.MessageBoxResult 值,用於指定使用者單擊了哪個訊息框按鈕。</returns>        public static MessageBoxResult Show( string messageBoxText, string caption )        {            return MessageBoxModule.Show( messageBoxText, caption );        }        /// <summary>        /// 顯示一個訊息框,該訊息框包含訊息、標題欄標題和按鈕,並且返回結果。        /// </summary>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <param name="caption"> 一個 System.String,用於指定要顯示的標題欄標題。</param>        /// <param name="button">一個 System.Windows.MessageBoxButton 值,用於指定要顯示哪個按鈕或哪些按鈕。</param>        /// <returns>一個 System.Windows.MessageBoxResult 值,用於指定使用者單擊了哪個訊息框按鈕。</returns>        public static MessageBoxResult Show( string messageBoxText, string caption, MessageBoxButton button )        {            return MessageBoxModule.Show( messageBoxText, caption, button );        }        /// <summary>        /// 在指定視窗的前面顯示訊息框。該訊息框顯示訊息並返回結果。        /// </summary>        /// <param name="owner">一個 System.Windows.Window,表示訊息框的所有者視窗。</param>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <returns> 一個 System.Windows.MessageBoxResult 值,用於指定使用者單擊了哪個訊息框按鈕。</returns>        public static MessageBoxResult Show( Window owner, string messageBoxText )        {            return MessageBoxModule.Show( owner, messageBoxText );        }        /// <summary>        ///  在指定視窗的前面顯示訊息框。該訊息框顯示訊息、標題欄標題和按鈕,並且返回結果。        /// </summary>        /// <param name="owner"> 一個 System.Windows.Window,表示訊息框的所有者視窗。</param>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <param name="caption"> 一個 System.String,用於指定要顯示的標題欄標題。</param>        /// <param name="button">一個 System.Windows.MessageBoxButton 值,用於指定要顯示哪個按鈕或哪些按鈕。</param>        /// <returns> 一個 System.Windows.MessageBoxResult 值,用於指定使用者單擊了哪個訊息框按鈕。</returns>        public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, MessageBoxButton button )        {            return MessageBoxModule.Show( owner, messageBoxText, caption, button );        }        /// <summary>        /// 在指定視窗的前面顯示訊息框。該訊息框顯示訊息、標題欄標題和按鈕,並且支援自定義按鈕和動作。        /// </summary>        /// <param name="owner"> 一個 System.Windows.Window,表示訊息框的所有者視窗。</param>        /// <param name="messageBoxText">一個 System.String,用於指定要顯示的文字。</param>        /// <param name="caption"> 一個 System.String,用於指定要顯示的標題欄標題。</param>        /// <param name="ctrlButtons">一組自定義的按鈕和響應動作。</param>        /// <returns>始終為 MessageBoxResult.None ,返回結果在此無意義。</returns>        public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, IList<MessageBoxButtonInfo> ctrlButtons )        {            return MessageBoxModule.Show( owner, messageBoxText, caption, ctrlButtons );        }        #endregion // Show functions    } 

簡單吧?只是對MessageBoxModule的呼叫而已.為了讓使用者必須使用 MessageBox類而無法使用 MessageBoxModule 類.我們修改其限定:

internal sealed class MessageBoxModule : Window{ //.........}

這回在外部看不到 MessageBoxModule了吧. MessageBox.Show(......) OY~ 安逸的很~

為了提供對自定義樣式 顏色的支援. 我們也加入了一些其他的方法:

        #region Public Static Functions      // 設定 訊息框中響應按鈕的樣式. 靜態儲存.針對所有呼叫的訊息框.        public static void SetDefaultCtorButtonStyle( Style buttonStyle )        {            CTRL_BUTTON_STYLE = buttonStyle;        }      // 設定 訊息框中的 標題 文字 邊框 前景 背景等 以配合我們的應用程式主題風格.      // 其中 MessageBoxCustomInfo 為自定義的結構 儲存以上的資訊.public static void SetMessageBoxCustomDefine( MessageBoxCustomInfo mbCustomIf )        {            if ( !default( MessageBoxCustomInfo ).Equals( mbCustomIf ) )            {                MessageBoxModule.MB_CUSTOMINFO = mbCustomIf;                MessageBoxModule.B_USED_CUSTOM_BRUSHES = true;            }            else            {                MessageBoxModule.MB_CUSTOMINFO = default( MessageBoxCustomInfo );                MessageBoxModule.B_USED_CUSTOM_BRUSHES = false;            }        }        public static void ResetMessageBoxCustomDefine()        {            CTRL_BUTTON_STYLE = Button.StyleProperty.DefaultMetadata.DefaultValue as Style;            MB_CUSTOMINFO = default( MessageBoxCustomInfo );            B_USED_CUSTOM_BRUSHES = false;        }        #region Show MessageBox Functions

MessageBoxCustomInfo結構:

    /// <summary>    /// MIV.Bus.IEMS.MessageBox 自定義資訊結構.    /// </summary>    public struct MessageBoxCustomInfo    {        #region private fields      // 一下布林值表示 那些屬性為有效的. 在其有效時 才在MessageBox中賦值,否則 繼續使用預設提供的值.        private bool isBackgroundChanged;        private bool isTitleForegroundChanged;        private bool isForegroundChanged;        private bool isBorderBrushChanged;        private bool isBorderThicknessChanged;        private Brush mb_background;        private Brush mb_title_foreground;        private Brush mb_foreground;        private Brush mb_borderbrush;        private Thickness mb_borderthickness;        #endregion // private fields        #region public properties        public bool IsBackgroundChanged        {            get { return isBackgroundChanged; }        }        public bool IsTitleForegroundChanged        {            get { return isTitleForegroundChanged; }        }        public bool IsForegroundChanged        {            get { return isForegroundChanged; }        }        public bool IsBorderBrushChanged        {            get { return isBorderBrushChanged; }        }        public bool IsBorderThicknessChanged        {            get { return isBorderThicknessChanged; }        }        public Brush MB_Background        {            get { return mb_background; }            set            {                mb_background = value;                isBackgroundChanged = true;            }        }        public Brush MB_Title_Foreground        {            get { return mb_title_foreground; }            set            {                mb_title_foreground = value;                isTitleForegroundChanged = true;            }        }        public Brush MB_Foreground        {            get { return mb_foreground; }            set            {                mb_foreground = value;                isForegroundChanged = true;            }        }        public Brush MB_Borderbrush        {            get { return mb_borderbrush; }            set            {                mb_borderbrush = value;                isBorderBrushChanged = true;            }        }        public Thickness MB_BorderThickness        {            get { return mb_borderthickness; }            set            {                mb_borderthickness = value;                isBorderThicknessChanged = true;            }        }        #endregion // public properties    }

IsUseCustomInfoDefine方法: 上面曾被2次略過....(=.=!) 判斷是否使用自定義的資訊(說的就是 MessageBoxCustomInfo 啦)

        private static void IsUseCustomInfoDefine( ref MessageBoxModule mbox )        {        // 判斷每一個屬性,有效時才賦值 否則忽略.            if ( B_USED_CUSTOM_BRUSHES && null != mbox )            {                if ( MB_CUSTOMINFO.IsBackgroundChanged )                {                    mbox.Background = MB_CUSTOMINFO.MB_Background;                }                if ( MB_CUSTOMINFO.IsBorderBrushChanged )                {                    mbox.BorderBrush = MB_CUSTOMINFO.MB_Borderbrush;                }                if ( MB_CUSTOMINFO.IsBorderThicknessChanged )                {                    mbox.BorderThickness = MB_CUSTOMINFO.MB_BorderThickness;                }                if ( MB_CUSTOMINFO.IsForegroundChanged )                {                    mbox.Foreground = MB_CUSTOMINFO.MB_Foreground;                }                if ( MB_CUSTOMINFO.IsTitleForegroundChanged )                {                    mbox.TitleForeground = MB_CUSTOMINFO.MB_Title_Foreground;                }            }        }

具體呼叫方法:

    // 修改預設的主題顏色.        Vito.Csharp.Wpf.Controls.MessageBox.SetMessageBoxCustomDefine( new MessageBoxCustomInfo()             {                 MB_Background = Brushes.Red,                 MB_Borderbrush = Brushes.Orange,                 MB_BorderThickness = new Thickness( 4 ),                 MB_Foreground = Brushes.White,                 MB_Title_Foreground = Brushes.Green             } );// 先設定自定義資訊,再呼叫ShowVito.Csharp.Wpf.Controls.MessageBox.Show( this, "文字資訊文字資訊文字資訊文字資訊", "header", MessageBoxButton.YesNo );

 自定義 Messagebox 的響應按鈕資訊 的使用方法:

            #region 自定義 Messagebox 的響應按鈕資訊.             List<MessageBoxButtonInfo> list = new List<MessageBoxButtonInfo>();            list.Add( new MessageBoxButtonInfo( "按鈕Yes", MessageBoxResult.Yes, new Action<object>( ( o ) =>                { // 這裡是 點選的響應動作 Action 上面已經講過.                    Vito.Csharp.Wpf.Controls.MessageBox.Show( "你點選了按鈕Yes" );                } ) ) );            list.Add( new MessageBoxButtonInfo( "按鈕No", MessageBoxResult.No, new Action<object>( ( o ) =>            {                Vito.Csharp.Wpf.Controls.MessageBox.Show( "你點選了按鈕No" );            } ) ) );            list.Add( new MessageBoxButtonInfo( "按鈕OK", MessageBoxResult.OK, new Action<object>( ( o ) =>            {                Vito.Csharp.Wpf.Controls.MessageBox.Show( "你點選了按鈕OK" );            } ) ) );            list.Add( new MessageBoxButtonInfo( "按鈕Cancel", MessageBoxResult.Cancel, new Action<object>( ( o ) =>            {                Vito.Csharp.Wpf.Controls.MessageBox.Show( "你點選了按鈕Cancel" );            } ) ) );            list.Add( new MessageBoxButtonInfo( "按鈕Cancel1", MessageBoxResult.Cancel, new Action<object>( ( o ) =>            {                Vito.Csharp.Wpf.Controls.MessageBox.Show( "你點選了按鈕Cancel1" );            } ) ) );            #endregion //            // 呼叫            r = Vito.Csharp.Wpf.Controls.MessageBox.Show( this, "文字資訊文字資訊文字資訊文字資訊文字資訊文字資訊", "Header", list );

好了到此就已經完成了.XAML資源也貼下一吧

<ResourceDictionary    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="clr-namespace:Vito.Csharp.Wpf.Controls">    <SolidColorBrush x:Key="TM_SubHeaderBackground"                     Color="#FF2D64A0" />    <SolidColorBrush x:Key="TM_MouseOverBorderBrush"                     Color="#FFA4BBD4" />    <SolidColorBrush x:Key="TM_SubTitleForeground"                     Color="#FFFBFBFB" />    <SolidColorBrush x:Key="TM_Textbackground"                     Color="#FFD9DFEC" />    <SolidColorBrush x:Key="TM_BackgroundBrush"                     Color="#ffd1e7ff" />    <SolidColorBrush x:Key="TM_ButtonNormalBorder"                     Color="Transparent" />    <LinearGradientBrush x:Key="TM_ButtonMouseOverBackground"                         EndPoint="0.5,1"                         StartPoint="0.5,0">        <GradientStop Color="#FF0D66C4" />        <GradientStop Color="#FF328FF3"                      Offset="1" />    </LinearGradientBrush>    <LinearGradientBrush x:Key="TM_ButtonPressBackground"                         EndPoint="0.5,1"                         StartPoint="0.5,0">        <GradientStop Color="#FF0D66C4" />        <GradientStop Color="#FF0B498B"                      Offset="1" />    </LinearGradientBrush>    <SolidColorBrush x:Key="TM_TransparentBrush"                     Color="Transparent" />                         <RadialGradientBrush  x:Key="MessageBoxBackground"                                 GradientOrigin="0.158,0.301"                                     Center="0.544,0.54"                                     RadiusY="0.842"                                     RadiusX="0.664">                    <GradientStop Color="#FFC0D8F3"                                  Offset="1" />                    <GradientStop Color="#FFF0F6FD" />                </RadialGradientBrush>            <Style x:Key="MessageBoxButtonStyle"           TargetType="{x:Type Button}">        <Setter Property="Focusable"                Value="False" />        <!--<Setter Property="Foreground"                Value="{DynamicResource TM_SubTitleForeground}" />-->        <Setter Property="Padding"                Value="2" />        <Setter Property="BorderThickness"                Value="1" />        <Setter Property="Background"                Value="{DynamicResource TM_BackgroundBrush}" />        <Setter Property="BorderBrush"                Value="{DynamicResource TM_TransparentBrush}" />        <Setter Property="Foreground"                Value="{DynamicResource TM_SubHeaderBackground}" />        <Setter Property="HorizontalAlignment"                Value="Center" />        <Setter Property="VerticalAlignment"                Value="Center" />        <Setter Property="HorizontalContentAlignment"                Value="Center" />        <Setter Property="VerticalContentAlignment"                Value="Center" />        <Setter Property="Template">            <Setter.Value>                <ControlTemplate TargetType="{x:Type Button}">                    <Border x:Name="Bd"                            BorderBrush="{TemplateBinding BorderBrush}"                            BorderThickness="{TemplateBinding BorderThickness}"                            Background="{TemplateBinding Background}"                            Padding="{TemplateBinding Padding}"                            SnapsToDevicePixels="True">                        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"                                          Content="{TemplateBinding Content}"                                          ContentStringFormat="{TemplateBinding ContentStringFormat}"                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />                    </Border>                    <ControlTemplate.Triggers>                        <Trigger Property="IsMouseOver"                                 Value="True">                            <Setter Property="BorderBrush"                                    TargetName="Bd"                                    Value="#FF3399FF" />                            <Setter Property="Background"                                    TargetName