【问题标题】:Problems with binding values绑定值的问题
【发布时间】:2015-01-15 13:22:31
【问题描述】:

我在将值绑定到控件时遇到问题。我检查了我拥有的其他窗口,我想我也是这样做的。 我想在主窗口打开之前显示类似从 App 加载窗口的内容。问题是没有任何变化(控件的文本/内容/值)。

初始化窗口:

public InitializationWindow()
{
    ...
    InitializationWindowClass.Progress = new InitializationWindowClass();
    this.mainSP.DataContext = InitializationWindowClass.Progress;
}

和 xaml 的一部分:

<StackPanel Name="mainSP" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="0, 0, 0, 10">
    <TextBlock x:Name="tblProgress" FontSize="14" Text="{Binding ProgressText}" TextAlignment="Center" TextWrapping="Wrap" />
    <Grid>
            <telerik:RadProgressBar x:Name="progress" Value="{Binding ProgressValue}" telerik:StyleManager.Theme="Summer" Height="25" IsIndeterminate="False" />
            <Label x:Name="lblPercent" FontWeight="Bold" Content="{Binding ProgressValueString}" HorizontalAlignment="Center" VerticalContentAlignment="Center" />
    </Grid>
</StackPanel>

初始化窗口类:

public class InitializationWindowClass : INotifyPropertyChanged
{
    public static InitializationWindowClass Progress { get; set; }
    private string progressText = String.Empty, progressValueString = String.Empty;
    private int progressValue = 0;
    public event PropertyChangedEventHandler PropertyChanged;

    public string ProgressText
    {
        get
        {
            return progressText;
        }
        set
        {
            progressText = value;
            NotifyPropertyChanged("ProgressText");
        }
    }

    public string ProgressValueString
    {
        get
        {
            return progressValueString;
        }
        set
        {
            progressValueString = value;
            NotifyPropertyChanged("ProgressValueString");
        }
    }

    public int ProgressValue
    {
        get
        {
            return progressValue;
        }
        set
        {
            progressValue = value;
            ProgressValueString = String.Format("{0}%", progressValue);
            NotifyPropertyChanged("ProgressValue");
            NotifyPropertyChanged("ProgressValueString");
        }
    }

    private void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

和 App.xaml.cs 的一部分:

protected override void OnStartup(StartupEventArgs e)
{
    InitializationWindow iw = new InitializationWindow(); 
    iw.Show();
    InitializationWindowClass.Progress.ProgressValue = Convert.ToInt32(((decimal)count / (decimal)sum) * 100);
    InitializationWindowClass.Progress.ProgressText = "Some text";
    ...
    ...
    InitializationWindowClass.Progress.ProgressValue = Convert.ToInt32(((decimal)count / (decimal)sum) * 100);
    InitializationWindowClass.Progress.ProgressText = "New text";
    ...
    ...
}

我检查过,当我更改 App.xaml.cs 中的 ProgressValue 时,该值正在更改 - 转到

get
{
    return progressValue;
}

所以问题是 - 我做错了什么?

【问题讨论】:

  • 在更新进度调用之间的 OnStartup() 方法期间发生了什么?您是否正在执行一些长期运行的任务?这些任务是否在主 UI 线程上运行?

标签: c# wpf xaml data-binding binding


【解决方案1】:

这是一个线程问题。绑定更改被发布到 Dispatcher,然后 UI 线程将这些事件从 Dispatcher 队列中拉出并处理它们。

在这里,您正在更改 OnStartup 事件中的绑定,该事件本身由 UI 线程处理。这意味着在退出 OnStartup 事件之前不会处理这些绑定更改。您最终在用户界面中看到的可能只是这些进度属性上次更改时的值。

您需要做的是将进度报告移至另一个线程。换句话说,使用async/await 或其他线程机制将当前在OnStartup 事件中完成的工作转移到不同的线程。


原始错误答案如下:

ProgressTextProgressValueStringProgressValue 都是 InitializationWindowClass 上的属性,而不是 InitializationWindow。看起来您需要将StackPanel 上的DataContext 设置为指向InitializationWindowProgress 属性,或者将Progress 属性包含在各个元素的绑定路径中。

也就是说,要么这样:

<StackPanel ... DataContext="{Binding Progress}">
    ... rest the same ...
</StackPanel>

或者这个:

<StackPanel ...>
    <TextBlock ... Text="{Binding Progress.ProgressText}" ... />
    <Grid>
        <telerik:RadProgressBar ... Value="{Binding Progress.ProgressValue}" ... />
        <Label ... Content="{Binding Progress.ProgressValueString}" ... />
    </Grid>
</StackPanel>

【讨论】:

  • 正如我之前写的: public InitializationWindow() { ... InitializationWindowClass.Progress = new InitializationWindowClass(); this.mainSP.DataContext = InitializationWindowClass.Progress;我在 InitializationWindow() 构造函数中有这个;)
  • 抱歉,没注意到
【解决方案2】:

你正在做的事情不会奏效。您正在显示初始屏幕并在同一线程上执行加载操作。这样,当您的加载操作运行时,主 UI 线程很忙并且没有更新,即使后台数据正在正确更改。这就是为什么您可能会看到“等待”光标,您的启动窗口没有响应,并且您的主窗口甚至可能根本没有出现。

  • SplashScreen 应该显示在不同的线程上
  • 您必须有一种与该线程通信的方式,因为:
  • 您不能使用另一个线程从一个线程直接更新 UI

Here 你有一个在 wpf 中使用 SplashScreen 的好例子

【讨论】:

  • 谢谢!现在可以使用 :) 很好的建议,效果很好,标记为答案
猜你喜欢
  • 2017-01-26
  • 1970-01-01
  • 2022-01-23
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多