How to link data between script.py and ui.XAML file?

I am collecting all the generic annotation families in project using the below line of code in my scripy.py file

Generic_Anno_Famlies = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsElementType().ToElements();

I have a separate ui file for wpf as shown below

I want to bind annotation family names to a combo box in my ui file. I am confused how we can link data in script.py file to ui.XAML file

If you are new to WPF, it’s going to be a bumpy ride in the beginning.
Do you really need a custom UI, or is it sufficient to use pre-written forms in pyRevit or rpw package?

Check out Effective Inputs in pyRevit docs, maybe SelectFromList will be enough for you. It’s quite well documented.

I’ve shared my 2 cents on pyRevit input forms here: Login | MailerLite
You might like the idea of using FlexForm from rpw package.

If you really need custom UI, you should be comfortable writing classes in python.
You can try to look at my example in my github repository of EF-Tools
lib → GUI → select_from_dict.py select_from_dict.xaml (or something along these lines)

I made it when I was still learning about WPF, so it’s not perfect, but it works and I am lazy to rewrite it nicer.

1 Like

Thanks @ErikFrits
I am not much familiar writing classes in python . I have used C# classes and an intermediate in WPF. So I think best way to get a result is to use pre-written forms in PyRevit as you suggested. Meanwhile could you please give me an example how to bind combo box using python classes.

Here is my script.py code

from pyrevit import revit
from pyrevit import forms,script,EXEC_PARAMS,UI
from Autodesk.Revit.UI.Selection import *
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('IronPython.wpf')

import clr
import sys
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Electrical import*
from Autodesk.Revit.DB.Mechanical import*
from Autodesk.Revit.DB.Architecture import *
from Autodesk.Revit.DB.Analysis import *




uiapp = __revit__
uidoc = uiapp.ActiveUIDocument
doc = uiapp.ActiveUIDocument.Document


import wpf #This is the wpf engine which is coming from IronPython.wpf which will be used to load xaml file
from System import Windows

from pyrevit import script
xamlfile = script.get_bundle_file('ui.xaml') #This will search this ui file in the current bundle and get that file.


#Collectors
Anno_Family_Names = []


Generic_Anno_Famlies = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsElementType().ToElements()


   


class CustomISelectionFilter(ISelectionFilter):
    def __init__(self, category_name):
        self.category_name = category_name
    def AllowElement(self, e):
        if e.Category.Name == self.category_name:
            return True
        else:
            return False
    def AllowReference(self, ref, point):
        return true
        
       
        
        
        
        
        
        
        
        
class MyWindow(Windows.Window):
    def __init__(self):
        wpf.LoadComponent(self,xamlfile) #self is the instance of the class and we are loading xaml file into that instance
        self.vm = ViewModel()
    def btn_Click_SelectPipe(self,sender,args):
        try:
            self.Hide()
            Pipe_Sel = uidoc.Selection.PickObject(ObjectType.Element,CustomISelectionFilter("Pipes"),"Select a Pipe")
            self.Show()
            
        except:
            UI.TaskDialog.Show("Operation canceled","Canceled by the user")
        
            
   


   
__doc__ = """  This tool will place flow aroows in pipes.

Tip : Select the pipe in network and then run the script.

Shift + Click : This mode will place arrows in the reverse direction."""
__title__ = 'Pipe  \n Flow Arrow'
__author__ = 'Jobin Sunny'


MyWindow().ShowDialog() 

here is my UI.XAML code

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		Title="MainWindow" Height="400" Width="600"  WindowStartupLocation="CenterScreen"  ResizeMode="CanResize" MinHeight="400" MinWidth="600">
		<Grid>
			<Grid.ColumnDefinitions>
				<ColumnDefinition Width="20" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50"/>
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50"/>
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="*" />
				<ColumnDefinition Width="50" />
				<ColumnDefinition Width="20" />
			</Grid.ColumnDefinitions>
			<Grid.RowDefinitions>
				<RowDefinition Height ="20" />
				<RowDefinition Height ="50" />
				<RowDefinition Height ="50" />
				<RowDefinition Height ="50" />
				<RowDefinition Height ="50" />
				<RowDefinition Height ="*" />
				<RowDefinition Height ="50" />
				<RowDefinition Height ="20" />
			</Grid.RowDefinitions>
			<Button  x:Name="btn_Select_Pipe" Content="Select Pipe" Grid.Column="9" Grid.Row="3"  Grid.ColumnSpan="2" Background="LightBlue"  Margin="10,0,10,20" Click="btn_Click_SelectPipe"/>              
			<Label Content="Pipe Arrow Placer " Foreground="#BF301A" FontWeight="Bold" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" Grid.Row="1"  Grid.ColumnSpan="7" Margin="10,0,10,20"/>
			<Label Content="Select a Pipe from pipe Network " Foreground="#BF301A" FontWeight="Bold" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="3"  Grid.ColumnSpan="7" Margin="10,0,10,20"/>
			<Label Content="Select Flow Arrow Family " Foreground="#BF301A" FontWeight="Bold" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4"  Grid.ColumnSpan="7" Margin="10,0,10,20"/>
        <ComboBox x:Name="ComboBox_AnnoFamily" Grid.Column="9" Grid.Row="4"  Grid.ColumnSpan="2" Background="LightBlue"  Margin="10,0,10,20" ItemsSource="{Binding Anno_Family_Names}">
			</ComboBox>

    </Grid>
		
</Window>