我正试图在我的主窗口中加入一个进度条,当一个按钮被按下时,按钮正在运行它的进程。我知道我只是缺少一些简单的东西,但我仍然是WPF的新手,因为我主要使用Windows窗体。
我的XML结构如下:
<Window x:Class="Program1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Program1"
mc:Ignorable="d"
Title="Program1" Height="1029" Width="1300" SnapsToDevicePixels="True" BorderThickness="0" Margin="0" ResizeMode="NoResize" Closing="Window_Closing"
x:Name="FirstWindow">
<Grid x:Name="Grid1">
<Button x:Name="btnPopulate" Content="Populate" HorizontalAlignment="Left" Margin="243,66,0,0" VerticalAlignment="Top" Width="118" Height="29" Click="btnPopulate_Click"/>
<Button x:Name="btnClear" Content="Clear" HorizontalAlignment="Left" Margin="366,66,0,0" VerticalAlignment="Top" Width="118" Height="29" Click="btnClear_Click"/>
<ProgressBar x:Name="progressBar" HorizontalAlignment="Left" Height="30" Margin="10,943,0,0" VerticalAlignment="Top" Width="351"/>
</Grid>
</Window>
字符串
我的populate button click方法如下:
private void btnPopulate_Click(object sender, RoutedEventArgs e)
{
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
for (int n = 0; n < 100; n++)
{
Thread.Sleep(50);
progressBar.Value = n;
};
}
));
backgroundThread.Start();
}
型
我遇到的问题是,我得到了这个错误:
当前上下文中不存在名称“progressBar”
我不确定如何从按钮单击方法访问progressBar控件。
我知道我可能错过了一些简单的东西,但我仍然试图得到WPF的窍门。
4条答案
按热度按时间a0x5cqrl1#
你不能从一个没有创建控件的线程访问控件(旧的Win32限制)。你必须使用UI Sync Context从后台线程访问UI元素,类似这样
在类定义字段的某处
字符串
然后使用它:
型
您还可以使用TaskTable来使用任务:
型
然后定义它
型
和使用
型
k5ifujac2#
简化版本:启动另一个不能修改UI-Thread-Content的
Thread
。这个解决方案解决了这个问题,但您仍然需要了解
MVVM
字符串
mwyxok5s3#
应该使用
Dispatcher.Invoke
或Dispatcher.BeginInvoke
方法,因为progressBar
属于另一个线程。字符串
使用
型
你的代码应该可以正常工作,除非名字中有一些错别字。
请参阅this post以获得填充ProgressBar的更好选择。
此外,Grid和
Margin
并不是一个好的选择。相反,使用DockPanel
或在Grid中添加RowDefinitions或ColumnDefinitions。t1rydlwq4#
你的
btnPopulate_Click()
方法声明在哪里?如果在MainWindow
类中,那么包含元素引用的字段应该存在。请提供一个好的Minimal, Complete, and Verifiable code example,它可以可靠地重现你描述的编译时错误消息。同时...
请注意,您的代码在其他方面也是完全错误的。最好使用MVVM,并简单地在视图模型属性上设置进度条状态值,将该属性绑定到进度条。您还应该使用其他机制,而不是启动专用线程来处理后台操作。我理解您发布的代码只是为了练习,但养成正确做事的习惯是件好事
这里有一些选择,会比你现在有更好的,也会比其他两个答案张贴到目前为止。
如果处理一个长时间运行的操作,并且该操作具有良好的间歇性检查点,您可以在其中报告进度:
首先,定义视图模型:
字符串
然后在窗口的C#代码中:
型
然后在XAML中,将视图模型的
ProgressValue
属性绑定到ProgressBar.Value
属性:型
如果你的长时间运行的操作实际上是由较小的异步操作组成的,那么你可以这样做:
型
请注意,在第二个示例中,您可以完全跳过视图模型,因为progress值的赋值发生在UI线程中,因此直接赋值给
ProgressBar.Value
属性是安全的。但无论如何,您仍然应该使用视图模型,因为这更符合标准WPF范例和WPF API的期望(也就是说,你可以用另一种方式来做,但你会与WPF API的设计者的意图作斗争,这将导致更多的挫折和困难)。