Wpf progressbar

can’t figure out how to make it work…
I have a progressbar in xaml:

<ProgressBar x:Name="pbar" Height="30" Margin="0,0,0,0" VerticalAlignment="Center" Width="500" HorizontalAlignment="Center"/>

and I have a class in my python script:

class CreateProgressWindow(Window):
    def __init__(self):
        wpf.LoadComponent(self, os.path.dirname(__file__) + '\window.xaml')

    def update(self, value):
        self.pbar.Value = value
        if self.pbar.Value == self.pbar.Maximum:
            self.Close()

I want to make the value jump inside a for loop:

progressform = CreateProgressWindow()
progressform.ShowDialog()
for i in range(100):
    CreateProgressWindow.update(i)

does anyone know how to fix it? really can’t find any info on this…
Thanks!

Hi,

you have some issues with threads:

  • ShowDialog() blocks the current thread
  • A wpf control can only be modified by the thread that owns it.

wpf progressbar


import clr	
import sys
import System
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\DLLs')

try:
	clr.AddReference("IronPython.Wpf")
	clr.AddReference('System.Core')
	clr.AddReference('System.Xml')
	clr.AddReference('PresentationCore')
	clr.AddReference('PresentationFramework')
	clr.AddReferenceByPartialName("WindowsBase")
except IOError:
	raise
	
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application

try:
	import wpf
	import time
except ImportError:
	raise

class CreateProgressWindow(Window):
	LAYOUT = '''
	<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		Title="WindowPgb5"
		Height="300"
		Width="300">
		<Grid>
			<ProgressBar
				Grid.Column="0"
				Grid.Row="0"
				HorizontalAlignment="Left"
				VerticalAlignment="Top"
				Margin="40,122,0,0"
				Width="210"
				Height="20"
				x:Name="pbar" />
		</Grid>
	</Window>
	'''
	
	def __init__(self):
		self.ui = wpf.LoadComponent(self, StringReader(CreateProgressWindow.LAYOUT))
		
	def _dispatch_updater(self):
		# ask WPF dispatcher for gui update
		self.pbar.Dispatcher.Invoke(System.Action(self._update_pbar),
									System.Windows.Threading.DispatcherPriority.Background)

	def _update_pbar(self):
		self.pbar.Value = self.new_value
		if self.pbar.Value == self.pbar.Maximum:
			self.Close()
	
	def update_progress(self, value):
		self.new_value = value
		self._dispatch_updater()

			
pb = CreateProgressWindow()
pb.Show()
for i in range(1, 101):
	time.sleep(0.05)
	pb.update_progress(i)

you have a good example here

https://github.com/eirannejad/pyRevit/blob/528940e1a3593f1ae5bd9bfd964d2f37fb9d45e1/pyrevitlib/pyrevit/forms/__init__.py

10 Likes

You can also see the pyRevit example run if you install pyRevit and the developer tool extensions. Pretty cool.

1 Like

thank you so much! @c.poupin :smile:
really appreciate!

@c.poupin by the way can I use binding method in wpf to control progressbar value? like:

<ProgressBar x:Name="pbar" Value="{Binding new_value}" Height="30" Margin="0,0,0,0" VerticalAlignment="Center" Width="500" HorizontalAlignment="Center"/>

I don’t know, I guess it is necessary to use MVVM model and event

1 Like