here an example
code (IronPython3)
import clr
import sys
import System
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
import System.Windows.Controls
from System.Windows.Controls import *
from System.Windows.Data import IMultiValueConverter, Binding, MultiBinding, IValueConverter
from System.Windows.Media import Brushes
import wpf
class NonNumericConverter(IMultiValueConverter):
#
def __init__(self):
super().__init__()
def Convert(self, values, targetType, parameter, culture):
text = values[0]
out_intValue = clr.Reference[System.Int32]()
out_decimalValue = clr.Reference[System.Decimal]()
if System.Int32.TryParse(text, out_intValue) or System.Decimal.TryParse(text, out_decimalValue):
return Brushes.White
else:
return Brushes.Tomato
def ConvertBack(self, value, targetType, parameter, culture):
raise NotImplementedError()
class MyWindow(Window):
LAYOUT = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window5"
Height="300"
Width="300">
<Grid>
<TextBox
Grid.Column="0"
Grid.Row="0"
VerticalAlignment="Top"
Height="20"
Margin="86,128,84,0"
x:Name="textBox" />
</Grid>
</Window>'''
def __init__(self):
super().__init__()
self.ui = wpf.LoadComponent(self, StringReader(MyWindow.LAYOUT))
# Create the binding
binding = MultiBinding()
converter = NonNumericConverter()
binding.Converter = converter
# Bind the Text property of the TextBox
text_binding = Binding("Text")
text_binding.Source = self.textBox
binding.Bindings.Add(text_binding)
# Apply the binding to the Background property
self.textBox.SetBinding(TextBox.BackgroundProperty , binding)
objWpf = MyWindow()
objWpf.ShowDialog()
OUT = 0
5 Likes
REDO10
October 11, 2024, 8:16pm
22
Thanks a lot @c.poupin
I’m on the move at the moment. I’ll try it later using pyrevit to see how it goes
Thanks.
3 Likes
REDO10
October 16, 2024, 8:27am
23
@c.poupin
c.poupin:
code (IronPython3)
After testing your code, I didn’t realize that you suggested using the IronPython3 engine to get it working. (I noticed that I’m using Revit 2023 and have IronPython2 installed), which causes an error in both python engines (Cpython3 and IronPython2 ) related to the missing wpf module and it gives me this error:
After doing some research on the web, I found a temporary solution to access IronPython.Wpf and use WPF modules by adding this line to your code:
from IronPython.Modules import Wpf as wpf
However, I still have an error related to loading xaml code in both Python engines, as follows:
If I use Cpython 3 engine, It gives me this error:
and if I use IronPython2 engine it gives me this error
So how can I solve this issue?
Another question: can I upgrade from IronPython2 to IronPython3 in Revit 2023? If so, how can I do that?
Edit:
I also tried to test your example where you used the IronPython2 engine with WPF, but it didn’t work for me and also WPF module is missing
Thanks.
Code for Ironpython2 (just remove super().__init__() special syntax for Python3)
import clr
import sys
import System
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
#
ipy2_assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(lambda a :all(x in a.FullName for x in ["IronPython.Modules", "2.7"]))
assembly_ipy2_Directory = System.IO.Path.GetDirectoryName( ipy2_assembly.Location )
parent_ipy2_Directory = System.IO.Directory.GetParent(assembly_ipy2_Directory).FullName
#
sys.path.append(parent_ipy2_Directory + "\\extra\\IronPython.StdLib.2.7.9")
sys.path.append(parent_ipy2_Directory + "\\bin")
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
import System.Windows.Controls
from System.Windows.Controls import *
from System.Windows.Data import IMultiValueConverter, Binding, MultiBinding, IValueConverter
from System.Windows.Media import Brushes
import wpf
class NonNumericConverter(IMultiValueConverter):
#
def Convert(self, values, targetType, parameter, culture):
text = values[0]
out_intValue = clr.Reference[System.Int32]()
out_decimalValue = clr.Reference[System.Decimal]()
if System.Int32.TryParse(text, out_intValue) or System.Decimal.TryParse(text, out_decimalValue):
return Brushes.White
else:
return Brushes.Tomato
def ConvertBack(self, value, targetType, parameter, culture):
raise NotImplementedError()
class MyWindow(Window):
LAYOUT = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window5"
Height="300"
Width="300">
<Grid>
<TextBox
Grid.Column="0"
Grid.Row="0"
VerticalAlignment="Top"
Height="20"
Margin="86,128,84,0"
x:Name="textBox" />
</Grid>
</Window>'''
def __init__(self):
self.ui = wpf.LoadComponent(self, StringReader(MyWindow.LAYOUT))
# Create the binding
binding = MultiBinding()
converter = NonNumericConverter()
binding.Converter = converter
# Bind the Text property of the TextBox
text_binding = Binding("Text")
text_binding.Source = self.textBox
binding.Bindings.Add(text_binding)
# Apply the binding to the Background property
self.textBox.SetBinding(TextBox.BackgroundProperty , binding)
objWpf = MyWindow()
objWpf.ShowDialog()
OUT = 0
for CPython3/PythonNet2 it’s a bit more complex, I’ll post the code later if you really need it
2 Likes
try to add
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
#
ipy2_assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(lambda a :all(x in a.FullName for x in ["IronPython.Modules", "2.7"]))
assembly_ipy2_Directory = System.IO.Path.GetDirectoryName( ipy2_assembly.Location )
parent_ipy2_Directory = System.IO.Directory.GetParent(assembly_ipy2_Directory).FullName
#
sys.path.append(parent_ipy2_Directory + "\\extra\\IronPython.StdLib.2.7.9")
sys.path.append(parent_ipy2_Directory + "\\bin")
I updated my post above
2 Likes
REDO10
October 16, 2024, 1:11pm
27
Sorry @c.poupin I add your last code but it’s still not working and wpf module is not loaded!!?
I searched for the IronPython 2.7 DLL in C:\Program Files (x86), and it does not exist. Could I be missing an installation of IronPython 2.7?
Thanks.
I don’t know, the wpf module is normally already present in the DSIronpython2 package.
I’m making a new correction, give it a try,
Code for Ironpython2 (just remove super().__init__() special syntax for Python3)
import clr
import sys
import System
clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)
#
ipy2_assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(lambda a :all(x in a.FullName for x in ["IronPython.Modules", "2.7"]))
assembly_ipy2_Directory = System.IO.Path.GetDirectoryName( ipy2_assembly.Location )
parent_ipy2_Directory = System.IO.Directory.GetParent(assembly_ipy2_Director…
REDO10
October 16, 2024, 5:58pm
30
@c.poupin
This code is driving me crazy, and I don’t know why it won’t work.
I checked my IronPython package and WPF dll are there
I tried your last correction but it still gives me the same error and wpf is not loaded
Question : As I explained in post #23 , why does adding the following line give me an error related to the LoadComponent function, which is part of wpf and not wpf itself? Does this mean that wpf is loaded in this case?
from IronPython.Modules import Wpf as wpf
Thanks.
try to update DSIronPython2 package to 2.5
there is maybe a conflict with another addin, pyRevit ?, RevitPythonShell?
1 Like
REDO10
October 17, 2024, 8:43am
32
@c.poupin
c.poupin:
try to update DSIronPython2 package to 2.5
there is maybe a conflict with another addin, pyRevit ?, RevitPythonShell?
I updated the DSIronPython2 package to version 2.5 as you suggested, and I confirm that there’s a conflict either with pyRevit or RevitPythonShell
With those two add-ins disabled, as you can see below, I can run your first script without needing to append sys with the WPF module (I only removed the super().__init__() syntax specific to Python 3 to make it work).
The question now is how to solve this issue permanently without disabling pyrevit and RevitPythonShell, as I need to use them!?
Thanks.
First make sure you’re on the latest version. Then if the issue persists reach out to the add-in provider - Dynamo and the community can’t help you here, only they can.
2 Likes
REDO10
October 19, 2024, 7:54pm
34
@c.poupin
I finally solved my issue by updating pyrevit from version 4.8.13 to 4.8.16, and I can now run your code in Dynamo without needing to disable pyrevit .
Question:
When I type a float number, the color of the input textbox changes to tomato. Does that mean the float number is not defined properly?
Thanks.
hi, try to see if it wouldn’t come from the decimal separator, or .
may be a lead or not
Sincerely
christian.stan
2 Likes
the syntax for the Net Framework is a little bit different
code for IronPython2 + Net Framework 4.8
import clr
import sys
import System
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
import System.Windows.Controls
from System.Windows.Controls import *
from System.Windows.Data import IMultiValueConverter, Binding, MultiBinding, IValueConverter
from System.Windows.Media import Brushes
import wpf
class NonNumericConverter(IMultiValueConverter):
#
def Convert(self, values, targetType, parameter, culture):
text = values[0]
out_intValue = clr.Reference[System.Int32]()
out_decimalValue = clr.Reference[System.Decimal]()
style = System.Globalization.NumberStyles.Number
culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-GB")
if System.Int32.TryParse(text, out_intValue) or System.Decimal.TryParse(text, style, culture, out_decimalValue):
return Brushes.White
else:
return Brushes.Tomato
def ConvertBack(self, value, targetType, parameter, culture):
raise NotImplementedError()
class MyWindow(Window):
LAYOUT = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window5"
Height="300"
Width="300">
<Grid>
<TextBox
Grid.Column="0"
Grid.Row="0"
VerticalAlignment="Top"
Height="20"
Margin="86,128,84,0"
x:Name="textBox" />
</Grid>
</Window>'''
def __init__(self):
self.ui = wpf.LoadComponent(self, StringReader(MyWindow.LAYOUT))
# Create the binding
binding = MultiBinding()
converter = NonNumericConverter()
binding.Converter = converter
# Bind the Text property of the TextBox
text_binding = Binding("Text")
text_binding.Source = self.textBox
binding.Bindings.Add(text_binding)
# Apply the binding to the Background property
self.textBox.SetBinding(TextBox.BackgroundProperty , binding)
objWpf = MyWindow()
objWpf.ShowDialog()
OUT = 0
code for IronPython3 + Net Core6+
import clr
import sys
import System
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
import System.Windows.Controls
from System.Windows.Controls import *
from System.Windows.Data import IMultiValueConverter, Binding, MultiBinding, IValueConverter
from System.Windows.Media import Brushes
import wpf
class NonNumericConverter(IMultiValueConverter):
#
def __init__(self):
super().__init__()
def Convert(self, values, targetType, parameter, culture):
text = values[0]
out_intValue = clr.Reference[System.Int32]()
out_decimalValue = clr.Reference[System.Decimal]()
if System.Int32.TryParse(text, out_intValue) or System.Decimal.TryParse(text, out_decimalValue):
return Brushes.White
else:
return Brushes.Tomato
def ConvertBack(self, value, targetType, parameter, culture):
raise NotImplementedError()
class MyWindow(Window):
LAYOUT = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window5"
Height="300"
Width="300">
<Grid>
<TextBox
Grid.Column="0"
Grid.Row="0"
VerticalAlignment="Top"
Height="20"
Margin="86,128,84,0"
x:Name="textBox" />
</Grid>
</Window>'''
def __init__(self):
super().__init__()
self.ui = wpf.LoadComponent(self, StringReader(MyWindow.LAYOUT))
# Create the binding
binding = MultiBinding()
converter = NonNumericConverter()
binding.Converter = converter
# Bind the Text property of the TextBox
text_binding = Binding("Text")
text_binding.Source = self.textBox
binding.Bindings.Add(text_binding)
# Apply the binding to the Background property
self.textBox.SetBinding(TextBox.BackgroundProperty , binding)
objWpf = MyWindow()
objWpf.ShowDialog()
OUT = 0
2 Likes
REDO10
October 20, 2024, 2:48pm
37
I tested the code in IronPython2, and it works fine. So far, I’ve gotten what I was looking for, and that resolves my issue.
Thanks a lot @c.poupin
1 Like