1

我有一个启动画面,应该在程序启动时显示加载过程。加载组件时,我无法更新标签中的文本。

从主启动 program.cs 我调用启动画面控制器中的 run() 方法。

startUpSplash.Run();

这里是控制器。这显示带有标签“正在初始化...”的启动画面

 public class StartUpSplashController
{
    public StartUpSplashViewModel ViewModel { get; set; }

    private StartUpSplashView starUpSplashWindow = new StartUpSplashView();
    private delegate void UIDelegate();
    public void Run()
    {
        InitializeViewModel();

        ViewModel.StatusMessage = "Initializing...";

        starUpSplashWindow.DataContext = ViewModel;
        starUpSplashWindow.Show();
    }



    public void UpdateStatus(string statusMessage)
    {
        starUpSplashWindow.Dispatcher.Invoke(new UIDelegate(delegate { ViewModel.StatusMessage = statusMessage; }));
        //ViewModel.StatusMessage = statusMessage;
    }

    public void End()
    {
        starUpSplashWindow.Close();
        starUpSplashWindow.InvalidateVisual();
    }

    private void InitializeViewModel()
    {
        ViewModel = new StartUpSplashViewModel(starUpSplashWindow);
        ViewModel.Controller = this;
    }
}

然后从主program.cs,因为发生了不同的事情,我也在启动控制器中调用了这个UpdateStatus方法。这是为了更新标签以显示正在发生的所有不同的事情。

这是应该更新的 lbl 的 Xaml。

 <Label Content="{Binding Path=StatusMessage, Mode=TwoWay, UpdateSourceTrigger= PropertyChanged}"  />

调用 UpdateStatus 方法时标签未更新。我注意到的一件奇怪的事情是,如果我做了

startupSplash.UpdateStatus("something");

进而

Messagebox.show("something"); 

消息框弹出后,初始屏幕显示更新的标签。

对此的任何帮助将不胜感激。

更新 2:这是视图模型

public class StartUpSplashViewModel : ViewModel<IView>
{
    [ImportingConstructor]
    public StartUpSplashViewModel(StartUpSplashView view)
        : base(view)
    {
    }

    public StartUpSplashController Controller { get; set; }

    private string _statusMessage;
    public string StatusMessage
    {
        get
        {
            return _statusMessage;
        }
        set
        {
            if (_statusMessage == value)
                return;

            _statusMessage = value;
            this.RaisePropertyChanged(s => s.StatusMessage);
        }
    }
}
4

3 回答 3

1

您是否尝试将更新放在启动窗口的正在运行的 UI 线程上?您可以使用 Dispatcher.Invoke 方法来执行此操作。首先,您必须声明一个委托:

private delegate void UIDelegate();

然后在 Dispatcher 中使用该委托:

starUpSplashWindow.Dispatcher.Invoke(new UIDelegate(delegate
{
    ViewModel.StatusMessage = statusMessage;
}));

这将在运行 UI 的线程上调用更新,这通常可以确保 UI 正确更新。

于 2011-11-15T20:26:12.033 回答
0

我不确定这是否会起作用,因为我没有尝试过,但希望它会起作用,请试一试:

在 SplashWindow.xaml.cs 视图文件中创建一个RefreshDelegateandRefresh方法,如下所示:

// To Refresh the UI immediately
private delegate void RefreshDelegate();
private static void Refresh(DependencyObject obj)
{
    obj.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render,
        (RefreshDelegate)delegate { });
}

修改UpdateStatusController中的方法如下:

public void UpdateStatus(string statusMessage)
{    
    ViewModel.StatusMessage = statusMessage;
    starUpSplashWindow.Refresh(starUpSplashWindow.statusLabel); //where statusLabel is the name of the Label
}
于 2011-11-16T05:58:47.870 回答
0

这就是我最终解决这个问题的方法。

我向 splashScreenController 添加了另一个方法,并在设置 ViewModel.Status 消息后从 UpdateStatus 中调用它。

 [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public void DoEvents()
    {
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
            new DispatcherOperationCallback(ExitFrame), frame);
        Dispatcher.PushFrame(frame);
    }

    public object ExitFrame(object f)
    {
        ((DispatcherFrame)f).Continue = false;

        return null;
    }
于 2011-11-16T20:34:21.430 回答