Jul 25, 2024

pyRevit WPF Form for Asking user for Multiple Paths

If you ever wanted to ask your users for multiple paths, you can use this custom WPF form.

EF-WPF Form

Here is the overview of the form that I will give you the code for.

It's simple, but yet very elegant to collect multiple paths. But also you can extend the functionality if you know how to work with WPF.

Happy Coding!

Folderstructure

To create WPF forms you need to create .xaml file and then use it inside of your python script.

Let's break them down one by one.

.XAML Script

Xaml - is the file format for WPF forms, which is used for designing front-end of the forms.

In this case you have to create a file FormFolderPaths.xaml in the same folder as yourscript.py, because I will be referencing the name of the file inside the python file.

Here is the code:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:av="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="av"
        Title="Folder Path Picker Form" 
        Height="400" Width="300">

    <StackPanel Margin="10">

        <!-- Title -->
        <TextBlock Text="Folder Path Picker Form" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Margin="0,0,0,10"/>

        <!-- Description -->
        <TextBlock TextWrapping="Wrap">
            <Run Text="This form allows you to pick three different folder paths. "/>
            <LineBreak/>
            <Run Text="Click the buttons to select the folders."/>
        </TextBlock>

        <!-- Separator -->
        <Separator Margin="0,10,0,10"/>

        <!-- Folder Path 1 -->
        <DockPanel Margin="0,0,0,10">
            <Label Content="Folder Path 1:" Height="25" DockPanel.Dock="Left"/>
            <Button Content="Browse..." Height="25" Width="Auto" Margin="5,0,0,0" Click="BrowseFolder1_Click"/>
        </DockPanel>
        <TextBox x:Name="FolderPath1" Height="25" Width="Auto" Margin="0,0,0,10" IsReadOnly="True"/>

        <!-- Folder Path 2 -->
        <DockPanel Margin="0,0,0,10">
            <Label Content="Folder Path 2:" Height="25" DockPanel.Dock="Left"/>
            <Button Content="Browse..." Height="25" Width="Auto" Margin="5,0,0,0" Click="BrowseFolder2_Click"/>
        </DockPanel>
        <TextBox x:Name="FolderPath2" Height="25" Width="Auto" Margin="0,0,0,10" IsReadOnly="True"/>

        <!-- Folder Path 3 -->
        <DockPanel Margin="0,0,0,10">
            <Label Content="Folder Path 3:" Height="25" DockPanel.Dock="Left"/>
            <Button Content="Browse..." Height="25" Width="Auto" Margin="5,0,0,0" Click="BrowseFolder3_Click"/>
        </DockPanel>
        <TextBox x:Name="FolderPath3" Height="25" Width="Auto" Margin="0,0,0,10" IsReadOnly="True"/>

        <!-- Submit Button -->
        <Button Content="Submit" Width="75" Height="25" HorizontalAlignment="Center" Click="UIe_button_run"/>

    </StackPanel>
</Window>


Script.py

And here is the python file with my template

# -*- coding: utf-8 -*-
__title__   = "Code Samples: WPF Form Sample"
__doc__ = """Version = 1.0
Date    = 15.07.2024
_____________________________________________________________________
Description:
Example of using WPF Form.
Keep in mind that WPF forms need a .xaml file that has the form design.
_____________________________________________________________________
How-To:
- Click the Button
_____________________________________________________________________
Last update:
- [15.07.2024] - V1.0 RELEASE
_____________________________________________________________________
Author: Erik Frits from LearnRevitAPI.com"""


# ╦╔╦╗╔═╗╔═╗╦═╗╔╦╗╔═╗
# ║║║║╠═╝║ ║╠╦╝ ╚═╗
# ╩╩ ╩╩  ╚═╝╩╚═ ╚═╝ IMPORTS
#====================================================================================================
from Autodesk.Revit.DB import *
from pyrevit import forms   # By importing forms you also get references to WPF package! Very IMPORTANT
import wpf, os, clr         # wpf can be imported only after pyrevit.forms!

# .NET Imports
clr.AddReference("System")
from System.Collections.Generic import List
from System.Windows import Window
from System.Windows.Forms import FolderBrowserDialog
import System

# ╦╔═╗╦═╗╦╔═╗╔╗ ╔═╗╔═╗
# ╚╗╔╝╠═╣╠╦╝║╠═╣╠╩╗║  ║╣ ╚═╗
#  ╚╝ ╩╩╚═╩╩ ╩╚═╝╩═╝╚═╝╚═╝ VARIABLES
#====================================================================================================
PATH_SCRIPT = os.path.dirname(__file__)
uidoc   = __revit__.ActiveUIDocument
app     = __revit__.Application
doc     = __revit__.ActiveUIDocument.Document #type: Document


# ╔╦╗╔═╗╦╔╗╔  ╔═╗╔═╗╦═╗╔╦╗
# ║║║╠═╣║║║║  ╠╣ ║╠╦╝║║║
# ╩╩ ╩╩╝╚╝  ╚═╝╩╚═╩ MAIN FORM
#====================================================================================================
class SimpleForm(Window):

    def __init__(self):
        # Connect to .xaml File (in same folder)
        path_xaml_file = os.path.join(PATH_SCRIPT, 'FormFolderPaths.xaml')
        wpf.LoadComponent(self, path_xaml_file)

        # Show Form
        self.ShowDialog()


    # ╔╦╗╔═╗╔╦╗╦ ╦╔═╗╔╦╗╔═╗
    # ║║║║╣  ╠═╣║ ║║╚═╗
    # ╩╚═╝ ╩╚═╝═╩╝╚═╝
    def browse_for_folder(self):
        dialog = FolderBrowserDialog()
        if dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK:
            return dialog.SelectedPath
        return None

    # ╔═╗╦═╗╔═╗╔═╗╔═╗╦═╗╔╦╗╦╔═╗╔═╗
    # ╠═╝╠╦╝║ ║╠═╝║╣ ╠╦╝ ║║╣ ╚═╗
    # ╩╚═╚═╝╩  ╚═╝╩╚═ ╩╚═╝╚═╝
    #====================================================================================================



    # ╔═╗╦  ╦╔═╗╔╗╔╔╦╗╔═╗
    # ║╣ ╚╗╔╝║╣ ║║║ ╚═╗
    # ╚═╝ ╚╝ ╚═╝╝╚╝ ╚═╝
    #====================================================================================================
    def BrowseFolder1_Click(self, sender, e):
        folder_path = self.browse_for_folder()
        if folder_path:
            self.FolderPath1.Text = folder_path

    def BrowseFolder2_Click(self, sender, e):
        folder_path = self.browse_for_folder()
        if folder_path:
            self.FolderPath2.Text = folder_path

    def BrowseFolder3_Click(self, sender, e):
        folder_path = self.browse_for_folder()
        if folder_path:
            self.FolderPath3.Text = folder_path

    # ╔╗ ╦╔╦╗╔╦╗╔═╗╔╗╔╔═╗
    # ╠╩╗║ ║║║║╚═╗
    # ╚═╝╚═╝ ╚═╝╝╚╝╚═╝ BUTTONS
    #==================================================
    def UIe_button_run(self, sender, e):
        """Button action: Rename view with given """
        self.Close()
        # You can do something here when button is clicked too.



#  ╦╔═╗╔═╗  ╔═╗╔═╗╦═╗╔╦╗
# ║╚═╗║╣   ╠╣ ║╠╦╝║║║
# ╚═╝╚═╝╚═╝  ╚═╝╩╚═╩ 
# Show form to the user
UI = SimpleForm()

# Get User Input
print('Path 1: {}'.format(UI.FolderPath1.Text))
print('Path 2: {}'.format(UI.FolderPath2.Text))
print('Path 3: {}'.format(UI.FolderPath3.Text))


Results

Join Newsletter

📩 You will be added to Revit API Newsletter

Join Us!

which is already read by 7400+ people!

Ready to become Revit Hero for your office? Learn Revit API!

Join this comprehensive course that will guide you step by step on how to create your dream tools for Revit that save time.