REVIT 2022 crashes after an external function call for a WPF window class

Hi

I’ve been struggling for two weeks now

I try to pass info from a cliquodrome to a function handling REVIT objects (so having to be outside the WPF class)
The WFP window work fine, if I test some function inside the class, it work well to but when I call external def …
With a basic class, no problem but with WPF … it’s stuck :frowning:

here is my code :
test.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		Title="MainWindow" Height="550" Width="1000" Opacity="0.8">
	<Grid>
		<CheckBox Content="Génie Civil" x:Name="Lot10" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="8,10,0,0" VerticalAlignment="Top" Width="100" />
			<CheckBox Content="10" x:Name="ChkBox10" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,30,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="11" x:Name="ChkBox11" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,50,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="12" x:Name="ChkBox12" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,70,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="13" x:Name="ChkBox13" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,90,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="14" x:Name="ChkBox14" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,110,0,0" VerticalAlignment="Top" Width="50" />
		<Button
			Content="GO"
			x:Name="BOUTTON" Click="Button_GO"
			HorizontalAlignment="Left" Margin="250,450,0,0" VerticalAlignment="Top" Width="150"
		/>
	</Grid>
</Window>

and script.py (on pyRevit context) :

# -*- coding: utf-8 -*-

from pyrevit import forms
import os
import wpf
from System.Windows import Application, Window


def test2(data):
    print "after wpf class ..."
    print data


class MyWindow(Window):

    def __init__(self):
        
        wpf.LoadComponent(self, os.path.dirname(__file__) + '\\test.xaml')

    def Button_GO(self, sender, e):
        disciplines = []
        for i in range(10, 15):
            moa = eval("self.ChkBox" + str(i))
            if moa.IsChecked:
                disciplines.append(str(i))
        print "inside wpf class"
        print disciplines
        test2(disciplines)


if __name__ == '__main__':
    MyWindow().Show()

and…
plantage REVIT-WPF

I try some stuff like that : revit api - pyRevit WPF non-modal trouble - Stack Overflow
but with same result : dirty crash

Please help ! :confused:

for information :

  • Windows 10
  • REVIT 2022.1.3
  • piRevit 4.8.12.22247+0031
  • Python 2.7.7.0 on .NET 4.0.30319.42000 64 bits

If I can help, there is an alternative solution for GUI, i use rpw.ui Forms : check this : Forms — Revit Python Wrapper 1.7.4 documentation

1 Like

I find the solution : Lesson 10. WPF forms. User Interface - YouTube

Note to all documentation writers.
It is always better to give an example :

  1. simple
  2. complete !
  3. which works !!!

Otherwise, the doc only confirms us in our ignorance :confused:

could you please let us now what was the actual problem and the solution? Thx!

I also had painful crashes when I was working with modeless UI-s. I guess the main reason is that all the events the WPF UI generates are running outside of pyrevits main exception handling scope (different thread?), which catches all unhandled exceptions, and shows an error message in the output window. You must have exception handling in the root of all your functions that are called by a UI event handler, or you’ll be sorry.

1 Like

The solution is to use WPFWindow and not Window :
test.xaml (not changed)

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		Title="MainWindow" Height="550" Width="1000" Opacity="0.8">
	<Grid>
		<CheckBox Content="Génie Civil" x:Name="Lot10" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="8,10,0,0" VerticalAlignment="Top" Width="100" />
			<CheckBox Content="10" x:Name="ChkBox10" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,30,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="11" x:Name="ChkBox11" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,50,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="12" x:Name="ChkBox12" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,70,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="13" x:Name="ChkBox13" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,90,0,0" VerticalAlignment="Top" Width="50" />
			<CheckBox Content="14" x:Name="ChkBox14" IsChecked="True" HorizontalAlignment="Left" Height="16" Margin="16,110,0,0" VerticalAlignment="Top" Width="50" />
		<Button
			Content="GO"
			x:Name="BOUTTON" Click="Button_GO"
			HorizontalAlignment="Left" Margin="250,450,0,0" VerticalAlignment="Top" Width="150"
		/>
	</Grid>
</Window>

and corrected script.py :

import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
from pyrevit.forms import WPFWindow
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument


def test2(data):
    print "after wpf class ..."
    print data



class ModalForm(WPFWindow):
    def __init__(self, xaml_file_name):
        WPFWindow.__init__(self, xaml_file_name)
        self.ShowDialog()
        
    def ChkBox_Click(self, sender, e):
        if sender.Name[:3] == "Lot":
            lot= int(sender.Name[3:5])
            #print lot
            nb=10
            if lot<30:
                nb=5
            for i in range(0,nb):
                moa = eval("self.ChkBox" + str(lot+i))
                moa.IsChecked=sender.IsChecked

    def Button_GO(self, sender, e):
        disciplines = []
        for i in range(10, 100):
            moa = eval("self.ChkBox" + str(i))
            if moa.IsChecked:
                disciplines.append(str(i))
        #mask(disciplines)
        test2(disciplines)

form = ModalForm('interface.xaml')

You also changed
.Show()
to:
.ShowDialog()
so basically from modeless form to modal.

2 Likes