WPF透明消息框

时间:2015-07-07 13:58:00

标签: wpf messagebox

是否可以向MessageBox添加自定义样式?

MessageBox.Show("Bla bla", "Error");

我想改变这个窗口的外观。我有什么选择?

1 个答案:

答案 0 :(得分:2)

这将有助于创建自定义消息框

 Background="Transparent" Closing="MessageBoxWindow_Closing"
        Loaded="Window_Loaded" RenderTransformOrigin="0.5, 0.5"
        ResizeMode="NoResize" ShowInTaskbar="False"
        SizeToContent="WidthAndHeight" 
        WindowStartupLocation="CenterOwner" WindowStyle="None">
    <Window.RenderTransform>
        <ScaleTransform x:Name="Scale"/>
    </Window.RenderTransform>
    <Window.Resources>

        <LinearGradientBrush x:Key="BackgroundBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#E4E9F0"/>
            <GradientStop Offset="1" Color="#D5DDED"/>
        </LinearGradientBrush>

        <Style TargetType="Label">
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="FontFamily" Value="Segoe UI"/>
            <Setter Property="FontSize" Value="12pt"/>
            <Setter Property="Foreground" Value="#FF003399"/>
        </Style>
        <Style TargetType="Image">
            <Setter Property="Height" Value="32"/>
            <Setter Property="Width" Value="32"/>
            <Setter Property="Margin" Value="3"/>
        </Style>

        <Storyboard x:Key="LoadAnimation">
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.15" From="0.6" Storyboard.TargetName="Scale" Storyboard.TargetProperty="(ScaleTransform.ScaleX)" To="1.1"/>
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.15" From="0.6" Storyboard.TargetName="Scale" Storyboard.TargetProperty="(ScaleTransform.ScaleY)" To="1.1"/>
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.15" From="0" Storyboard.TargetName="MessageBoxWindow" Storyboard.TargetProperty="(Window.Opacity)" To="1"/>
            <DoubleAnimation BeginTime="00:00:00.15" Duration="00:00:00.1" From="1.1" Storyboard.TargetName="Scale" Storyboard.TargetProperty="(ScaleTransform.ScaleX)" To="1"/>
            <DoubleAnimation BeginTime="00:00:00.15" Duration="00:00:00.1" From="1.1" Storyboard.TargetName="Scale" Storyboard.TargetProperty="(ScaleTransform.ScaleY)" To="1"/>
        </Storyboard>

        <Storyboard x:Key="UnloadAnimation">
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.2" From="1" Storyboard.TargetName="Scale"  Storyboard.TargetProperty="(ScaleTransform.ScaleX)" To="0.6"/>
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.2" From="1" Storyboard.TargetName="Scale" Storyboard.TargetProperty="(ScaleTransform.ScaleY)" To="0.6"/>
            <DoubleAnimation AccelerationRatio="0.4" Duration="00:00:00.2" From="1" Storyboard.TargetName="MessageBoxWindow" Storyboard.TargetProperty="(Window.Opacity)" To="0"/>
        </Storyboard>

        <Style  TargetType="{x:Type Button}">
            <Setter Property="FontSize" Value="15"/>
            <Setter Property="Width" Value="124"/>
            <Setter Property="Height" Value="42"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <Image x:Name="CancelButton" Source="pack://application:,,,/V-Coles;component/Resources/Images/openlockerbtn.png" />
                            <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsDefaulted" Value="true">
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source" TargetName="CancelButton" Value="pack://application:,,,/V-Coles;component/Resources/Images/openlockerbtnhover.png"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Source" TargetName="CancelButton" Value="pack://application:,,,/V-Coles;component/Resources/Images/openlockerbtnhover.png"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>
    <Border Height="150" Width="300" Background="#dd4739" Padding="7" Margin="50,100,50,50">
        <DockPanel LastChildFill="True">
            <StackPanel x:Name="ButtonsPanel" HorizontalAlignment="Center" DockPanel.Dock="Bottom" Orientation="Horizontal"/>
            <Image x:Name="ImagePlaceholder" DockPanel.Dock="Left"/>
            <Label x:Name="MessageLabel" DockPanel.Dock="Right">
                <TextBlock x:Name="MessageText" Foreground="Black" TextWrapping="Wrap"/>
            </Label>
        </DockPanel>
    </Border>
</Window>


public partial class MessageBox : INotifyPropertyChanged
    {
        #region Private Field


        private bool _animationRan;

        #endregion

        #region Constructor


        public MessageBox(Window owner, string message, string details, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
        {
            this._animationRan = false;

            this.InitializeComponent();

            Owner = owner ?? Application.Current.MainWindow;

            this.CreateButtons(button, defaultResult);

            this.CreateImage(icon);

            MessageText.Text = message;

            this.ApplyOptions(options);
        }

        #endregion

        #region Event Property


        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Public Property

        /// <summary>
        /// Gets or sets a value indicating whether the IsActiveMessageBox
        /// </summary>
        public static bool IsActiveMessageBox { get; set; }


        public static Window ActiveMessageBox { get; set; }


        public MessageBoxResult MessageBoxResult { get; set; }

        #endregion

        #region Public Static Method


        public static MessageBoxResult ShowInformation(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return ShowInformation(null, message, details, showCancel, options);
        }


        public static MessageBoxResult ShowInformation(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK, options);
        }


        public static MessageBoxResult ShowQuestion(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return ShowQuestion(null, message, details, showCancel, options);
        }


        public static MessageBoxResult ShowQuestion(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(owner, message, details, showCancel ? MessageBoxButton.YesNoCancel : MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes, options);
        }


        public static MessageBoxResult ShowWarning(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return ShowWarning(null, message, details, showCancel, options);
        }


        public static MessageBoxResult ShowWarning(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK, options);
        }


        public static MessageBoxResult ShowError(Exception exception, string message = "", MessageBoxOptions options = MessageBoxOptions.None)
        {
            return ShowError(null, exception, message, options);
        }


        public static MessageBoxResult ShowError(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return ShowError(null, message, details, showCancel, options);
        }


        public static MessageBoxResult ShowError(Window owner, Exception exception, string message = "", MessageBoxOptions options = MessageBoxOptions.None)
        {
            string details = string.Empty;
#if DEBUG
            details = exception.ToString();
#endif
            return Show(owner, string.IsNullOrEmpty(message) ? exception.Message : message, details, MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, options);
        }


        public static MessageBoxResult ShowError(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, options);
        }


        public static MessageBoxResult Show(string message, string details = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(null, message, details, button, icon, defaultResult, options);
        }


        public static MessageBoxResult Show(string message, MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(message, string.Empty, button, icon, defaultResult, options);
        }


        public static MessageBoxResult Show(Window owner, string message, MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
        {
            return Show(owner, message, string.Empty, button, icon, defaultResult, options);
        }


        public static MessageBoxResult Show(Window owner, string message, string details = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None)
        {
            MessageBoxResult result = MessageBoxResult.None;
            result = Application.Current.Dispatcher.Invoke(new Func<MessageBoxResult>(() =>
            {
                var messageBox = new MessageBox(owner, message, details, button, icon, defaultResult, options);
                IsActiveMessageBox = true;
                ActiveMessageBox = messageBox;
                messageBox.ShowDialog();

                return messageBox.MessageBoxResult;
            }));

            if (result != MessageBoxResult.None)
            {
                return (MessageBoxResult)result;
            }
            else
            {
                return MessageBoxResult.None;
            }
        }

        #endregion

        #region Public Method


        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler temp = this.PropertyChanged;
            if (temp != null)
            {
                temp(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region Private Method


        private void CreateButtons(MessageBoxButton button, MessageBoxResult defaultResult)
        {
            switch (button)
            {
                case MessageBoxButton.OK:
                    ButtonsPanel.Children.Add(this.CreateOkButton(defaultResult));
                    break;
                case MessageBoxButton.OKCancel:
                    ButtonsPanel.Children.Add(this.CreateOkButton(defaultResult));
                    ButtonsPanel.Children.Add(this.CreateCancelButton(defaultResult));
                    break;
                case MessageBoxButton.YesNoCancel:
                    ButtonsPanel.Children.Add(this.CreateYesButton(defaultResult));
                    ButtonsPanel.Children.Add(this.CreateNoButton(defaultResult));
                    ButtonsPanel.Children.Add(this.CreateCancelButton(defaultResult));
                    break;
                case MessageBoxButton.YesNo:
                    ButtonsPanel.Children.Add(this.CreateYesButton(defaultResult));
                    ButtonsPanel.Children.Add(this.CreateNoButton(defaultResult));
                    break;
                default:
                    throw new ArgumentOutOfRangeException("button");
            }
        }


        private Button CreateOkButton(MessageBoxResult defaultResult)
        {
            var okButton = new Button
            {
                Name = "okButton",
                Content = "OK",
                IsDefault = defaultResult == MessageBoxResult.OK,
                Tag = MessageBoxResult.OK,
            };

            okButton.Click += this.ButtonClick;

            return okButton;
        }


        private Button CreateCancelButton(MessageBoxResult defaultResult)
        {
            var cancelButton = new Button
            {
                Name = "cancelButton",
                Content = "Cancel",
                IsDefault = defaultResult == MessageBoxResult.Cancel,
                IsCancel = true,
                Tag = MessageBoxResult.Cancel,
            };

            cancelButton.Click += this.ButtonClick;

            return cancelButton;
        }


        private Button CreateYesButton(MessageBoxResult defaultResult)
        {
            var yesButton = new Button
            {
                Name = "yesButton",
                Content = "Yes",
                IsDefault = defaultResult == MessageBoxResult.Yes,
                Tag = MessageBoxResult.Yes,
            };

            yesButton.Click += this.ButtonClick;

            return yesButton;
        }


        private Button CreateNoButton(MessageBoxResult defaultResult)
        {
            var noButton = new Button
            {
                Name = "noButton",
                Content = "No",
                IsDefault = defaultResult == MessageBoxResult.No,
                Tag = MessageBoxResult.No,
            };

            noButton.Click += this.ButtonClick;

            return noButton;
        }


        private void ButtonClick(object sender, RoutedEventArgs e)
        {
            MessageBoxResult = (MessageBoxResult)(sender as Button).Tag;

            Close();
        }

        private void ApplyOptions(MessageBoxOptions options)
        {
            if ((options & MessageBoxOptions.RightAlign) == MessageBoxOptions.RightAlign)
            {
                MessageText.TextAlignment = TextAlignment.Right;
            }

            if ((options & MessageBoxOptions.RtlReading) == MessageBoxOptions.RtlReading)
            {
                FlowDirection = FlowDirection.RightToLeft;
            }
        }

        /// <summary>
        /// Create the image from the system's icons
        /// </summary>
        /// <param name="icon">MessageBox Icon</param>
        private void CreateImage(MessageBoxImage icon)
        {
            switch (icon)
            {
                case MessageBoxImage.None:
                    ImagePlaceholder.Visibility = Visibility.Collapsed;
                    break;
                case MessageBoxImage.Information:
                    ImagePlaceholder.Source = SystemIcons.Information.ToImageSource();
                    break;
                case MessageBoxImage.Question:
                    ImagePlaceholder.Source = SystemIcons.Question.ToImageSource();
                    break;
                case MessageBoxImage.Warning:
                    ImagePlaceholder.Source = SystemIcons.Warning.ToImageSource();
                    break;
                case MessageBoxImage.Error:
                    ImagePlaceholder.Source = SystemIcons.Error.ToImageSource();
                    break;
                default:
                    throw new ArgumentOutOfRangeException("icon");
            }
        }

        /// <summary>
        /// Show the startup animation
        /// </summary>
        /// <param name="sender">Sender parameter</param>
        /// <param name="e">Argument Parameter</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // This is set here to height after the width has been set 
            // so the details expander won't stretch the message box when it's opened
            SizeToContent = SizeToContent.Height;

            var animation = TryFindResource("LoadAnimation") as Storyboard;

            animation.Begin(this);
        }

        /// <summary>
        /// Show the closing animation
        /// </summary>
        /// <param name="sender">Sender parameter</param>
        /// <param name="e">Argument Parameter</param>
        private void MessageBoxWindow_Closing(object sender, CancelEventArgs e)
        {
            if (!this._animationRan)
            {
                // The animation won't run if the window is allowed to close, 
                // so here the animation starts, and the window's closing is canceled
                e.Cancel = true;

                var animation = TryFindResource("UnloadAnimation") as Storyboard;

                animation.Completed += this.AnimationCompleted;

                animation.Begin(this);
            }
        }

        /// <summary>
        /// Signals the closing animation ran, and close the window (for real this time)
        /// </summary>
        /// <param name="sender">Sender parameter</param>
        /// <param name="e">Argument Parameter</param>
        private void AnimationCompleted(object sender, EventArgs e)
        {
            this._animationRan = true;

            Close();
        }

        #endregion
    }