绑定值的问题
Problems with binding values
我在将值绑定到控件时遇到问题。我检查了我拥有的其他 windows,我认为我正在以同样的方式进行操作。
我想在 main window 打开之前显示类似从 App 加载 window 的内容。问题是什么都没有改变(text/content/value 个控件)。
初始化窗口:
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";
...
...
}
我检查过,当我更改时,即 ProgressValue 从 App.xaml.cs,该值正在更改 - 将变为
get
{
return progressValue;
}
所以问题是 - 我做错了什么?
这是线程问题。绑定更改发布到 Dispatcher,然后 UI 线程将这些事件从 Dispatcher 队列中拉出并处理它们。
此处您正在更改 OnStartup
事件中的绑定,该事件本身由 UI 线程处理。这意味着在退出 OnStartup
事件之前不会处理这些绑定更改。您最终在用户界面中看到的可能只是这些进度属性上次更改时的值。
您需要做的是将进度报告移至另一个线程。换句话说,使用 async
/await
或其他一些线程机制,将 OnStartup
事件中当前完成的工作转移到另一个线程。
原文错误答案如下:
ProgressText
、ProgressValueString
和 ProgressValue
都是 InitializationWindowClass
上的属性,而不是 InitializationWindow
。看起来您需要将 StackPanel
上的 DataContext
设置为指向 InitializationWindow
的 Progress
属性,或者包括 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>
你所做的是行不通的。您正在显示启动画面并在同一线程上执行加载操作。这样,当您的加载操作 运行 时,主 UI 线程很忙并且没有更新,即使后台数据正在正确更改也是如此。这就是为什么您可能会看到 "wait" 光标,启动画面 window 没有响应,并且您的主 window 甚至可能根本不会出现。
- SplashScreen 应该在不同的线程上显示
- 您必须有一种与该线程通信的方式,因为:
- 您不能使用另一个线程从一个线程直接更新 UI
Here 你有一个很好的在 wpf 中使用 SplashScreen 的例子
我在将值绑定到控件时遇到问题。我检查了我拥有的其他 windows,我认为我正在以同样的方式进行操作。 我想在 main window 打开之前显示类似从 App 加载 window 的内容。问题是什么都没有改变(text/content/value 个控件)。
初始化窗口:
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";
...
...
}
我检查过,当我更改时,即 ProgressValue 从 App.xaml.cs,该值正在更改 - 将变为
get
{
return progressValue;
}
所以问题是 - 我做错了什么?
这是线程问题。绑定更改发布到 Dispatcher,然后 UI 线程将这些事件从 Dispatcher 队列中拉出并处理它们。
此处您正在更改 OnStartup
事件中的绑定,该事件本身由 UI 线程处理。这意味着在退出 OnStartup
事件之前不会处理这些绑定更改。您最终在用户界面中看到的可能只是这些进度属性上次更改时的值。
您需要做的是将进度报告移至另一个线程。换句话说,使用 async
/await
或其他一些线程机制,将 OnStartup
事件中当前完成的工作转移到另一个线程。
原文错误答案如下:
ProgressText
、ProgressValueString
和 ProgressValue
都是 InitializationWindowClass
上的属性,而不是 InitializationWindow
。看起来您需要将 StackPanel
上的 DataContext
设置为指向 InitializationWindow
的 Progress
属性,或者包括 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>
你所做的是行不通的。您正在显示启动画面并在同一线程上执行加载操作。这样,当您的加载操作 运行 时,主 UI 线程很忙并且没有更新,即使后台数据正在正确更改也是如此。这就是为什么您可能会看到 "wait" 光标,启动画面 window 没有响应,并且您的主 window 甚至可能根本不会出现。
- SplashScreen 应该在不同的线程上显示
- 您必须有一种与该线程通信的方式,因为:
- 您不能使用另一个线程从一个线程直接更新 UI
Here 你有一个很好的在 wpf 中使用 SplashScreen 的例子