Hi All, @c.poupin
I’m implementing a UI using WPF to create grids in Revit. To allow users to switch between numeric values (‘1, 2, 3, …’) and alphabetic values (‘A, B, C, …’) for grid names, I used a ComboBox, as shown below.
However, I’m struggling to set up event handlers to manage the selection for each grid orientation (X and Y) and to prevent the user from selecting the same values for both X and Y.
Grid script + xaml layout
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 StackPanel, DockPanel, TextBlock, TextBox, Button, Separator
import wpf
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
class Grids(Window):
LAYOUT = '''
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Grids"
Height="Auto"
Width="300"
SizeToContent ="Height"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="10">
<!--Input LX-->
<StackPanel Margin="0,0,0,10">
<TextBlock Text ="Longueur Total suivant X (m):" Width="170" Height="25" HorizontalAlignment="Left" FontSize="12" FontWeight="Bold" />
<DockPanel Width="200" HorizontalAlignment="Left" >
<TextBlock Text =" Lx =" Width="50" Height="25" Margin="0,0,5,0" RenderTransformOrigin="1.733,0.495" />
<TextBox x:Name="input_Lx" Width="75" Margin="0,0,5,0" />
<TextBlock Text="m" Width="25" HorizontalAlignment="Left" />
</DockPanel>
</StackPanel>
<!--Input LY-->
<StackPanel Margin="0,0,0,10">
<TextBlock Text ="Longueur Total suivant Y (m):" Width="170" Height="25" HorizontalAlignment="Left" FontSize="12" FontWeight="Bold" />
<DockPanel Width="200" HorizontalAlignment="Left" >
<TextBlock Text =" Ly =" Width="50" Height="25" Margin="0,0,5,0" RenderTransformOrigin="1.733,0.495" />
<TextBox x:Name="input_Ly" Width="75" Margin="0,0,5,0" />
<TextBlock Text="m" Width="25" HorizontalAlignment="Left" />
</DockPanel>
</StackPanel>
<!--Grid Extension -->
<StackPanel Margin="0,0,0,10">
<TextBlock Text ="Extension des Axes X, Y (m):" Width="170" Height="25" HorizontalAlignment="Left" FontSize="12" FontWeight="Bold" />
<DockPanel Width="200" HorizontalAlignment="Left" >
<TextBlock Text =" e =" Width="50" Height="25" Margin="0,0,5,0" RenderTransformOrigin="1.733,0.495" />
<TextBox x:Name="input_extension" Width="75" Margin="0,0,5,0" />
<TextBlock Text="m" Width="25" HorizontalAlignment="Left" />
</DockPanel>
</StackPanel>
<!--Spacing along X axis -->
<StackPanel Margin="0,0,0,10">
<TextBlock Text ="Espacement suivant X (m):" Width="170" Height="25" HorizontalAlignment="Left" FontSize="12" FontWeight="Bold" />
<DockPanel Width="200" HorizontalAlignment="Left" >
<TextBlock Text =" dx =" Width="50" Height="25" Margin="0,0,5,0" RenderTransformOrigin="1.733,0.495" />
<TextBox x:Name="input_dx" Width="75" Margin="0,0,5,0" />
<TextBlock Text="m" Width="25" HorizontalAlignment="Left" />
</DockPanel>
</StackPanel>
<!--Spacing along Y axis -->
<StackPanel Margin="0,0,0,10">
<TextBlock Text ="Espacement suivant Y (m):" Width="170" Height="25" HorizontalAlignment="Left" FontSize="12" FontWeight="Bold" />
<DockPanel Width="200" HorizontalAlignment="Left" >
<TextBlock Text =" dy =" Width="50" Height="25" Margin="0,0,5,0" RenderTransformOrigin="1.733,0.495" />
<TextBox x:Name="input_dy" Width="75" Margin="0,0,5,0" />
<TextBlock Text="m" Width="25" HorizontalAlignment="Left" />
</DockPanel>
</StackPanel>
<!--bubbles symbol -->
<StackPanel>
<TextBlock Text="Choix de symbols pour Lx, Ly:" FontWeight="Bold"/>
<!-- Symbol Type for Lx -->
<DockPanel Margin="0,0,0,10">
<TextBlock Text="Type de symbole Lx:" Width="120"/>
<ComboBox x:Name="dropdown_symbol_x" Width="150" HorizontalAlignment="Right" >
<ComboBoxItem Content="1 2 3 ..." />
<ComboBoxItem Content="A B C ..." />
</ComboBox>
</DockPanel>
<!-- Symbol Type for Ly -->
<DockPanel Margin="0,0,0,10">
<TextBlock Text="Type de symbole Ly:" Width="120"/>
<ComboBox x:Name="dropdown_symbol_y" Width="150" HorizontalAlignment="Right" >
<ComboBoxItem Content="1 2 3 ..." />
<ComboBoxItem Content="A B C ..." />
</ComboBox>
</DockPanel>
</StackPanel>
<!--Separator, OK and Cancel Button-->
<Separator Margin="0,0,0,10"/>
<DockPanel HorizontalAlignment="Center">
<Button Content="OK" Width="75" Height="25" Margin="0,0,10,0" Click="OK_Clicked" />
<Button Content="Cancel" Width="75" Height="25" Click="Cancel_Clicked" />
</DockPanel>
</StackPanel>
</Window>'''
def __init__(self):
wpf.LoadComponent(self, StringReader(Grids.LAYOUT))
# Symbol sets
self.all_symbols_numeric = ['1', '2', '3', '4', '5'] # Numeric
self.all_symbols_alpha = ['A', 'B', 'C', 'D', 'E'] # Alphabetic
"""I'm struggling with how to handle the event triggered
by a user selection to correctly populate the symbols Sx and Sy in self.data
while preventing the user from selecting the same symbols for both Sx and Sy"""
self.selected_symbol_x = None
self.selected_symbol_y = None
self.data = {}
self.ShowDialog()
def _collect_input_data(self):
"""Collect and convert input data from the UI"""
try:
self.data = {
"Lx": _input_to_meters(self.input_Lx.Text),
"Ly": _input_to_meters(self.input_Ly.Text),
"e": _input_to_meters(self.input_extension.Text),
"dx": _input_to_meters(self.input_dx.Text),
"dy": _input_to_meters(self.input_dy.Text),
"Sx": [self.select_symbol_x.SelectedItem],
"Sy": [self.select_symbol_y.SelectedItem]
}
except ValueError:
TaskDialog.Show('error', 'Invalid input detected')
def OK_Clicked(self, sender, e):
self._collect_input_data()
# self.data
if not self.data:
return
self.Close()
def Cancel_Clicked(self, sender, e):
self.Close()
def _input_to_meters(value):
"""Convert a textual value to meters."""
return UnitUtils.ConvertToInternalUnits(float(value), UnitTypeId.Meters)
UI = Grids()
OUT = UI
Thanks.