REDO10
January 8, 2025, 2:30pm
1
Hi All, @c.poupin
I can’t load my own wpf control inside my main script where I’m getting this error:
Here is my Main Script
Main script
import clr
from sys import path
sys.path.append(r"D:\Examples_pyRevit\WPF_Forms")
clr.AddReference("IronPython.Wpf")
clr.AddReference('PresentationFramework')
clr.AddReference('PresentationCore')
clr.AddReference('WindowsBase')
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, TextBlock, Grid
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
import wpf
from TimePicker import TimePicker
class MainWindow(Window):
def __init__(self):
layout = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="400">
<Grid x:Name="My_Grid">
</Grid>
</Window>'''
wpf.LoadComponent(self, StringReader(layout))
self.populate_grid()
def populate_grid(self):
# Create a TabControl
tab_control = TabControl()
symbol = {"x": "X", "y": "Y", "z": "Z"}
for key in ["x", "y", "z"]:
text_block = TextBlock()
text_block.Text = "I'm a text block in : Tab {}".format(symbol[key])
text_block.FontSize = 20
text_block.FontWeight = FontWeights.UltraBold
text_block.FontStyle = FontStyles.Italic
tab_item = TabItem()
tab_item.Header = "Tab {}".format(symbol[key])
tab_item.Content = text_block
tab_control.Items.Add(tab_item)
time_picker = TimePicker()
time_picker_tab = TabItem()
time_picker_tab.Header = "Time Picker"
time_picker_tab.Content = time_picker
tab_control.Items.Add(time_picker_tab)
# Add the TabControl to the Grid
self.My_Grid.Children.Add(tab_control)
main_window = MainWindow()
OUT = main_window.ShowDialog()
and here is my own control script
TimePicker control
import clr
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
clr.AddReference("WindowsBase")
from System import DateTime
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from System.IO import StringReader
from System.Windows.Markup import XamlReader
import wpf
class TimePicker(UserControl):
def __init__(self):
self.hour = DateTime.Now.Hour
self.min = DateTime.Now.Minute
# Define the XAML string for the UserControl
layout = '''
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RepeatButton x:Name="btnIncreaseHour"
Content="+" FontSize="24"
Click="btnIncreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseHour"
Content="-" FontSize="24"
Grid.Row="1"
Click="btnDecreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnIncreaseMins"
Content="+" FontSize="24"
Grid.Column="2"
Click="btnIncreaseMins_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseMins"
Content="-" FontSize="24"
Grid.Column="2"
Grid.Row="1"
Interval="100" Click="btnDecreaseMins_Click"/>
<TextBox x:Name="tbxTimePicker"
FontSize="42"
Foreground="Blue"
Grid.Column="1"
Grid.RowSpan="2"
TextAlignment="Center"/>
</Grid>
</UserControl>'''
wpf.LoadComponent(self, StringReader(layout))
# Initialize the TextBox with the current time
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
# Attach event handlers
self.btnIncreaseHour.Click += self.btnIncreaseHour_Click
self.btnDecreaseHour.Click += self.btnDecreaseHour_Click
self.btnIncreaseMins.Click += self.btnIncreaseMins_Click
self.btnDecreaseMins.Click += self.btnDecreaseMins_Click
def btnIncreaseHour_Click(self, sender, e):
self.hour += 1
if self.hour == 24:
self.hour = 0
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnDecreaseHour_Click(self, sender, e):
self.hour -= 1
if self.hour == -1:
self.hour = 23
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnIncreaseMins_Click(self, sender, e):
self.min += 1
if self.min == 60:
self.min = 0
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnDecreaseMins_Click(self, sender, e):
self.min -= 1
if self.min == -1:
self.min = 59
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
please help me to solve this issue
Thanks.
Your code is not complete, but I tested with this code slightly modified and it works.
Note that I do not have the Blend SDK installed.
import clr
from sys import path
sys.path.append(r"E:\XXXX\py_module_test")
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, TextBlock, Grid
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
from System.Xml import XmlReader
from System import DateTime
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from System.Windows import LogicalTreeHelper
from System.Windows.Markup import XamlReader, XamlWriter
import wpf
if "TimePicker" in sys.modules:
del sys.modules["TimePicker"]
from TimePicker import TimePicker
class MainWindow(Window):
def __init__(self):
layout = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="400">
<Grid x:Name="My_Grid">
</Grid>
</Window>'''
wpf.LoadComponent(self, StringReader(layout))
self.populate_grid()
def populate_grid(self):
# Create a TabControl
tab_control = TabControl()
symbol = {"x": "X", "y": "Y", "z": "Z"}
for key in ["x", "y", "z"]:
text_block = TextBlock()
text_block.Text = "I'm a text block in : Tab {}".format(symbol[key])
text_block.FontSize = 20
text_block.FontWeight = FontWeights.UltraBold
text_block.FontStyle = FontStyles.Italic
tab_item = TabItem()
tab_item.Header = "Tab {}".format(symbol[key])
tab_item.Content = text_block
tab_control.Items.Add(tab_item)
time_picker = TimePicker()
time_picker_tab = TabItem()
time_picker_tab.Header = "Time Picker"
time_picker_tab.Content = time_picker
tab_control.Items.Add(time_picker_tab)
# Add the TabControl to the Grid
self.My_Grid.Children.Add(tab_control)
main_window = MainWindow()
OUT = main_window.ShowDialog()
TimePicker.py
import clr
from sys import path
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, TextBlock, Grid
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
from System.Xml import XmlReader
from System import DateTime
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from System.Windows import LogicalTreeHelper
import wpf
class TimePicker(UserControl):
def __init__(self):
self.hour = DateTime.Now.Hour
self.min = DateTime.Now.Minute
# Define the XAML string for the UserControl
layout = '''
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RepeatButton x:Name="btnIncreaseHour"
Content="+" FontSize="24"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseHour"
Content="-" FontSize="24"
Grid.Row="1"
Interval="100"/>
<RepeatButton x:Name="btnIncreaseMins"
Content="+" FontSize="24"
Grid.Column="2"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseMins"
Content="-" FontSize="24"
Grid.Column="2"
Grid.Row="1"
Interval="100" />
<TextBox x:Name="tbxTimePicker"
FontSize="42"
Foreground="Blue"
Grid.Column="1"
Grid.RowSpan="2"
TextAlignment="Center"/>
</Grid>
</UserControl>'''
wpf.LoadComponent(self, StringReader(layout))
# Initialize the TextBox with the current time
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
# Attach event handlers
#self.btnIncreaseHour.Click += self.btnIncreaseHour_Click
2 Likes
REDO10
January 8, 2025, 5:10pm
3
@c.poupin
I’ve placed the “TimePicker.xaml” file in the same directory as the script “TimePicker.py”. I want to keep it outside this later and load it using a path that I define inside the script with wpf.LoadComponent(self, "xaml_path")
, but I’m getting an error and I’m confused about how to do that!!
here the xaml for TimePicker:
TimePicker.xaml
<UserControl x:Class="My_Control.My_user_control.TimePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:My_Control.My_user_control"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RepeatButton x:Name="btnIncreaseHour"
Content="+" FontSize="24"
Click="btnIncreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseHour"
Content="-" FontSize="24"
Grid.Row="1"
Click="btnDecreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnIncreaseMins"
Content="+" FontSize="24"
Grid.Column="2"
Click="btnIncreaseMins_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseMins"
Content="-" FontSize="24"
Grid.Column="2"
Grid.Row="1"
Interval="100" Click="btnDecreaseMins_Click"/>
<TextBox x:Name="tbxTimePicker"
FontSize="42"
Foreground="Blue"
Grid.Column="1"
Grid.RowSpan="2"
TextAlignment="Center"/>
</Grid>
</UserControl>
and here the completed script for TimePicker
TimePicker.py
import clr
import os
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System import DateTime
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from wpf import LoadComponent
import wpf
script_path = os.path.dirname(__file__)
class TimePicker(UserControl):
def __init__(self):
# Load the XAML layout
xaml_path = os.path.join(script_path, 'TimePicker.xaml')
wpf.LoadComponent(self, "xaml_path")
self.hour = DateTime.Now.Hour
self.min = DateTime.Now.Minute
self.update_time_display()
def update_time_display(self):
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnIncreaseHour_Click(self, sender, e):
self.hour += 1
if self.hour == 24:
self.hour = 0
self.update_time_display()
def btnDecreaseHour_Click(self, sender, e):
self.hour -= 1
if self.hour == -1:
self.hour = 23
self.update_time_display()
def btnIncreaseMins_Click(self, sender, e):
self.min += 1
if self.min == 60:
self.min = 0
self.update_time_display()
def btnDecreaseMins_Click(self, sender, e):
self.min -= 1
if self.min == -1:
self.min = 59
self.update_time_display()
Thanks
remove this x:Class="My_Control.My_user_control.TimePicker"
from your TimePicker.xaml
and replace in your TimePicker.py
wpf.LoadComponent(self, "xaml_path")
by
wpf.LoadComponent(self, xaml_path)
2 Likes
REDO10
January 9, 2025, 9:53am
5
@c.poupin
c.poupin:
remove this x:Class="My_Control.My_user_control.TimePicker"
from your TimePicker.xaml
and replace in your TimePicker.py
wpf.LoadComponent(self, "xaml_path")
by
wpf.LoadComponent(self, xaml_path)
Even though I applied your suggestions, I can’t load TimePicker.xaml
if it is outside of TimePicker.py
. Although I placed it in the same folder as TimePicker.py
on my desktop, as shown in the image below, I still encountered this error:
Furthermore, in the script below, UC
, where TimePicker.xaml
is inside TimePicker.py
, the WPF form is displayed with the TimePicker
control, but its events are not working!?
TimePicker + xaml
import clr
import os
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, TextBlock, Grid
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
from System.Xml import XmlReader
from System import DateTime
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from System.Windows import LogicalTreeHelper
import wpf
script_path = os.path.dirname(__file__)
class TimePicker(UserControl):
def __init__(self):
self.hour = DateTime.Now.Hour
self.min = DateTime.Now.Minute
# Define the XAML string for the UserControl
layout = '''
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RepeatButton x:Name="btnIncreaseHour"
Content="+" FontSize="24"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseHour"
Content="-" FontSize="24"
Grid.Row="1"
Interval="100"/>
<RepeatButton x:Name="btnIncreaseMins"
Content="+" FontSize="24"
Grid.Column="2"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseMins"
Content="-" FontSize="24"
Grid.Column="2"
Grid.Row="1"
Interval="100" />
<TextBox x:Name="tbxTimePicker"
FontSize="42"
Foreground="Blue"
Grid.Column="1"
Grid.RowSpan="2"
TextAlignment="Center"/>
</Grid>
</UserControl>'''
wpf.LoadComponent(self, StringReader(layout))
self.update_time_display()
def update_time_display(self):
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnIncreaseHour_Click(self, sender, e):
self.hour += 1
if self.hour == 24:
self.hour = 0
self.update_time_display()
def btnDecreaseHour_Click(self, sender, e):
self.hour -= 1
if self.hour == -1:
self.hour = 23
self.update_time_display()
def btnIncreaseMins_Click(self, sender, e):
self.min += 1
if self.min == 60:
self.min = 0
self.update_time_display()
def btnDecreaseMins_Click(self, sender, e):
self.min -= 1
if self.min == -1:
self.min = 59
self.update_time_display()
UC
import clr
from sys import path
sys.path.append(r"C:\Users\nono\Desktop\Time")
clr.AddReference("IronPython.Wpf")
clr.AddReference('PresentationFramework')
clr.AddReference("System.Xml")
clr.AddReference('PresentationCore')
clr.AddReference('WindowsBase')
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, Grid
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
from System.Xml import XmlReader
from System import DateTime
from System.Windows import RoutedEventArgs
from System.Windows.Controls import UserControl
from System.Windows import LogicalTreeHelper
from System.Windows.Markup import XamlReader, XamlWriter
import wpf
if "TimePicker" in sys.modules:
del sys.modules["TimePicker"]
from TimePicker import TimePicker
#from TimePicker import TimePicker # Import the translated TimePicker class
class MainWindow(Window):
def __init__(self):
# Load the XAML layout
xaml_content = """
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="My_Grid">
</Grid>
</Window>"""
wpf.LoadComponent(self, StringReader(xaml_content))
self.populate_grid()
def populate_grid(self):
# Create a TabControl
tab_control = TabControl()
# Add a tab with the TimePicker control
time_picker = TimePicker()
tab_item_time_picker = TabItem()
tab_item_time_picker.Header = "Time Picker"
tab_item_time_picker.Content = time_picker
tab_control.Items.Add(tab_item_time_picker)
# Add example tabs
for i in range(3):
tab_item = TabItem()
tab_item.Header = "Tab {}".format(i + 1)
tab_item.Content = "Content {}".format(i + 1)
tab_control.Items.Add(tab_item)
self.My_Grid.Children.Add(tab_control)
main_window = MainWindow()
OUT = main_window.ShowDialog()
What am I missing that prevents me from loading TimePicker.xaml
outside of TimePicker.py
, and how can I fix the issue with TimePicker
’s events?
Thanks.
see your file extension … TimePicker.xaml
or TimePicker.xml
?
1 Like
REDO10
January 9, 2025, 2:02pm
7
Oh, my bad! I wrote my code with Notepad++ , which saved the file with the xml
extension instead of xaml
, and I didn’t notice that! Now the code works perfectly.
@c.poupin do you have an idea how I can add the xaml
extension in Notepad++ so that I can save my files with this extension by default in the future?
Here updated scripts:
TimePicker.xaml
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RepeatButton x:Name="btnIncreaseHour"
Content="+" FontSize="24"
Click="btnIncreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseHour"
Content="-" FontSize="24"
Grid.Row="1"
Click="btnDecreaseHour_Click"
Interval="100"/>
<RepeatButton x:Name="btnIncreaseMins"
Content="+" FontSize="24"
Grid.Column="2"
Click="btnIncreaseMins_Click"
Interval="100"/>
<RepeatButton x:Name="btnDecreaseMins"
Content="-" FontSize="24"
Grid.Column="2"
Grid.Row="1"
Interval="100" Click="btnDecreaseMins_Click"/>
<TextBox x:Name="tbxTimePicker"
FontSize="42"
Foreground="Blue"
Grid.Column="1"
Grid.RowSpan="2"
TextAlignment="Center"/>
</Grid>
</UserControl>
TimePicker.py
import clr
import os
clr.AddReference("IronPython.Wpf")
clr.AddReference("PresentationFramework")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
from System.Windows import Application, Window
from System.IO import StringReader
from System import DateTime
from System.Windows.Controls import UserControl
import wpf
script_path = os.path.dirname(__file__)
class TimePicker(UserControl):
def __init__(self):
# Load the XAML layout
xaml_path = os.path.join(script_path, 'TimePicker.xaml')
wpf.LoadComponent(self, xaml_path)
self.hour = DateTime.Now.Hour
self.min = DateTime.Now.Minute
self.update_time_display()
def update_time_display(self):
self.tbxTimePicker.Text = "{:02d} : {:02d}".format(self.hour, self.min)
def btnIncreaseHour_Click(self, sender, e):
self.hour += 1
if self.hour == 24:
self.hour = 0
self.update_time_display()
def btnDecreaseHour_Click(self, sender, e):
self.hour -= 1
if self.hour == -1:
self.hour = 23
self.update_time_display()
def btnIncreaseMins_Click(self, sender, e):
self.min += 1
if self.min == 60:
self.min = 0
self.update_time_display()
def btnDecreaseMins_Click(self, sender, e):
self.min -= 1
if self.min == -1:
self.min = 59
self.update_time_display()
UC2_Dynamo
import clr
from sys import path
sys.path.append(r"C:\Users\nono\Desktop\Time2")
clr.AddReference("IronPython.Wpf")
clr.AddReference('PresentationFramework')
clr.AddReference('PresentationCore')
clr.AddReference('WindowsBase')
from System.Windows import Application, Window
from System.Windows.Controls import TabControl, TabItem, TextBlock
from System.Windows import FontWeights, FontStyles
from System.IO import StringReader
import wpf
from TimePicker import TimePicker
class MainWindow(Window):
def __init__(self):
xaml_content = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="My_Grid">
</Grid>
</Window>'''
wpf.LoadComponent(self, StringReader(xaml_content))
self.populate_grid()
def populate_grid(self):
# Create a TabControl
tab_control = TabControl()
symbol = {"x": "X", "y": "Y", "z": "Z"}
for key in ["x", "y", "z"]:
text_block = TextBlock()
text_block.Text = "I'm a text block in : Tab {}".format(symbol[key])
text_block.FontSize = 20
text_block.FontWeight = FontWeights.UltraBold
text_block.FontStyle = FontStyles.Italic
tab_item = TabItem()
tab_item.Header = "Tab {}".format(symbol[key])
tab_item.Content = text_block
tab_control.Items.Add(tab_item)
# Create an instance object from the User Control TimePicker
time_picker = TimePicker()
tab_item_time_picker = TabItem()
tab_item_time_picker.Header = "Time Picker"
tab_item_time_picker.Content = time_picker
tab_control.Items.Add(tab_item_time_picker)
# Add the TabControl to the Grid
self.My_Grid.Children.Add(tab_control)
main_window = MainWindow()
OUT = main_window.ShowDialog()
Thanks.
1 Like