进度条未在自定义初始屏幕上更新

时间:2014-06-12 00:49:30

标签: c# wpf windows xaml splash-screen

所以我试图让一个启动画面有一个进度条,随着我的应用程序加载而递增。显然我不得不编辑代码来删除任何IP,幸好大部分都很简单,没有一个真正重要。但是,任何帮助将不胜感激。

解决方案1失败

以下是我的应用程序块的代码:

public class App : Application
{
   public void Run()
   {
      bool isLoaded = false;

      ProgressSplashScreen splashScreen = new ProgressSplashScreen(() => { isLoaded = true; });
      splashScreen.Show();
      SpinWait.SpinUntil(() => isLoaded);

      _bootStrapper = new BootStrapper(splashScreen);
      _bootStrapper.Run();

      splashScreen.Close();
    }
}

以下是我的启动画面XAML的代码:

<Window x:Class="Application.ProgressSplashScreen"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Splash" BorderBrush="Transparent"
        AllowsTransparency="True" 
        Icon="../../Resources/Icons/Icon.ico"
        WindowStartupLocation="CenterScreen" 
        WindowStyle="None" Width="640" Height="520" 
        Background="Transparent" Name="SplashWindow" Topmost="True" >
   <Grid>
       <StackPanel Orientation="Vertical" VerticalAlignment="Stretch"
                   HorizontalAlignment="Stretch">
            <Image Source="../../Resources/Images/splash.jpg" Height="480" Width="640"/>
            <Grid>
               <ProgressBar Name="SplashProgress" Height="20" Minimum="0" Maximum="100"
                            BorderBrush="Transparent" />
               <Label Name="SplashMessage" VerticalAlignment="Bottom" 
                      HorizontalAlignment="Center"/>
            </Grid>
       </StackPanel>
    </Grid>
</Window>

Splash Screen XAML的代码背后:

using System;
using System.Threading;
using System.Windows;

namespace Application
{
    public partial class ProgressSplashScreen : Window
    {
        private SynchronizationContext _synchContext;

        public ProgressSplashScreen(Action isLoaded)
        {
            this.Loaded += (sender, args) => isLoaded();
            InitializeComponent();
            _synchContext = SynchronizationContext.Current;
        }

        public void SetProgress(double progress, string message)
        {
            _synchContext.Send((state) =>
            {
                SplashProgress.Value = progress;
                SplashMessage.Content = message;        
            }, null);        
        }
    }
}

最后我试图通过以下方式进行更新调用的BootStrapper类:

namespace Application
{
    internal sealed class BootStrapper : BaseMefBootstrapper
    {
        private ProgressSplashScreen _splash;

        public BootStrapper(ProgressSplashScreen splashScreen)
        {
            _splash = splashScreen;
        }

        public void Run()
        {
           // removed do stuff code here
           _splash.SetProgress(10, "Loading stuff...");
           // removed do stuff code here
           _splash.SetProgress(40, "Loading stuff...");
           // removed do stuff code here
           _splash.SetProgress(80, "Loading stuff...");
           // removed do stuff code here
           _splash.SetProgress(90, "Loading stuff...");
           // removed do stuff code here
           _splash.SetProgress(100, "Loading stuff...");
        }
    }
}

到目前为止,我的屏幕上只有一个空的进度条......

解决方案2失败

ps ...我也试过

using System;
using System.Threading;
using System.Windows;

namespace Application
{
    public partial class ProgressSplashScreen : Window, INotifyPropertyChanged
    {
        private Dispatcher _dispatcher;
        public event PropertyChangedEventHandler PropertyChanged;
        private string _progressMessage;
        private double _progressValue;

        public string ProgressMessage
        {
            get { return _progressMessage; }
            set
            {
                _progressMessage = value;
                OnPropertyChanged("ProgressMessage");
             }
        }

        public double ProgressValue
        {
            get { return _progressValue; }
            set
            {
                _progressValue = value;
                OnPropertyChanged("ProgressValue");
            }
        }

        public ProgressSplashScreen(Action isLoaded)
        {
            this.Loaded += (sender, args) => isLoaded();
            InitializeComponent();
            _dispatcher = Dispatcher.CurrentDispatcher;
        }

        public void SetProgress(double progress, string message)
        {
            _dispatcher.BeginInvoke(new Action(() =>
            {
                ProgressValue = progress;
                ProgressMessage = message;
            }), DispatcherPriority.ContextIdle, null);       
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

将此作为XAML

<Window x:Class="Application.ProgressSplashScreen"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Splash" BorderBrush="Transparent"
        AllowsTransparency="True" 
        Icon="../../Resources/Icons/Icon.ico"
        WindowStartupLocation="CenterScreen" 
        WindowStyle="None" Width="640" Height="520" 
        Background="Transparent" Name="SplashWindow" Topmost="True" >
   <Grid>
       <StackPanel Orientation="Vertical" VerticalAlignment="Stretch"
                   HorizontalAlignment="Stretch">
            <Image Source="../../Resources/Images/splash.jpg" Height="480" Width="640"/>
            <Grid>

               <ProgressBar Name="SplashProgress" Height="20" Minimum="0" Maximum="100" 
                            BorderBrush="Transparent" Value="{Binding ProgressValue, 
                            UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
            <Label Name="SplashMessage" VerticalAlignment="Bottom" HorizontalAlignment="Center" 
                   Content="{Binding ProgressMessage, 
                   UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
            </Grid>
       </StackPanel>
    </Grid>
</Window>

任何帮助都会很棒!谢谢!真的很惊讶这就像现在看起来那么难......

1 个答案:

答案 0 :(得分:0)

所以我所说的是:

MainWindow.xaml

<Window x:Class="SplashSxreenExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Splashscreen" 
        WindowStyle="none" ResizeMode="NoResize" ShowInTaskbar="False" WindowStartupLocation="CenterScreen"
        Height="400" Width="700" Background="#FF292929" FontFamily="Century Gothic"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">


    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/SplashScrTemplate.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="AUto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Content="Test Splash Screen" Foreground="LightGray" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="60"/>
        <Label Grid.Row="1" Content="{Binding ProgressMessage}" Foreground="LightGray" FontStyle="Italic"/>
        <ProgressBar Grid.Row="2" Height="3" Foreground="White" Style="{StaticResource FlatProgressBar}"
                     Value="{Binding ProgressValue}"/>

    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace SplashSxreenExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged; 
        private string _progressMessage;
        private int _progressValue;
        private BackgroundWorker _mWorker;

        public MainWindow()
        {
            InitializeComponent();
            _mWorker = new BackgroundWorker();
            _mWorker.WorkerReportsProgress = true; //Allow reporting
            _mWorker.ProgressChanged += _mWorker_ProgressChanged;
            _mWorker.DoWork += _mWorker_DoWork;

            _mWorker.RunWorkerAsync();
        }

        void _mWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker wkr = sender as BackgroundWorker;

            wkr.ReportProgress(0, "Starting..."); //Reporting progress
            //Here do your stuff
            Thread.Sleep(500);
            wkr.ReportProgress(10, "Loading stuff...");
            //Here do your stuff
            Thread.Sleep(1000);
            wkr.ReportProgress(40, "Loading stuff 2...");
            //Here do your stuff
            Thread.Sleep(500);
            wkr.ReportProgress(80, "Loading stuff 3...");
            //Here do your stuff
            Thread.Sleep(1500);
            wkr.ReportProgress(90, "Loading stuff 4...");
            //Here do your stuff
            Thread.Sleep(2000);
            wkr.ReportProgress(100, "Finished");
        }

        void _mWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            ProgressValue = e.ProgressPercentage; //Value
            ProgressMessage = e.UserState.ToString(); //Message
        }

        #region Properties
        public string ProgressMessage
        {
            get { return _progressMessage; }
            set
            {
                _progressMessage = value;
                OnPropertyChanged("ProgressMessage");
            }
        }

        public int ProgressValue
        {
            get { return _progressValue; }
            set
            {
                _progressValue = value;
                OnPropertyChanged("ProgressValue");
            }
        }
        #endregion



        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

和资源词典(对于扁平条,以防万一)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="FlatProgressBar" TargetType="{x:Type ProgressBar}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ProgressBar">
                    <Border BorderBrush="{x:Null}" BorderThickness="0" Background="{x:Null}" CornerRadius="0" Padding="0">
                        <Grid x:Name="PART_Track">
                            <Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left" Fill="{Binding RelativeSource={RelativeSource AncestorType=ProgressBar},Path=Foreground}" />
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

这对我很有用,告诉我你是否有困难。

以下是结果的ptrscr:

Result snapshot 我希望它可以帮助你。

BR,

巴斯蒂安。