Dialog with button for selecting element

We are trying to have a button that once clicked will show a picker to select an element.
The following code works (once). Once clicked again an exception is thrown. Strangely it is printed in a different window (hint?).

This is the resulted of printing the exception:
This name ‘uidoc’ is not defined

Any suggestion on how to fix this would be appreciated?

gdict = globals()
uiapp = __revit__
uidoc = uiapp.ActiveUIDocument


class MyWindow(Windows.Window):
  def __init__(self):
    xaml_file_path = script.get_bundle_file('dialog/dialog.xaml')
    with open(xaml_file_path, 'r') as f:
      xaml_content = f.read()
    self.dialog = XamlReader.Parse(StringReader(xaml_content).ReadToEnd())
    self.select_button = self.dialog.FindName('selectButton')
    self.select_button.Click += self.handle_select_click

  def show(self):
    self.dialog.ShowDialog()

  def handle_select_click(self, sender, e):
    self.dialog.Dispatcher.Invoke(lambda: self.dialog.Hide())
    try:
      choices = uidoc.Selection
      hasPickOne = choices.PickObject(ObjectType.Element)
      if hasPickOne != None:
          print("One element selected.")
    except Exception as e: 
      print(e)
    self.dialog.Dispatcher.Invoke(lambda: self.dialog.Show())

MyWindow().show()

1 Like

For the record, tried a variation of a given example, and again it worked only for first click and then sent a similar exception.

Example that I was not able to re run:
[Select model element from UI upon button click]

The code I used:
from Autodesk.Revit.UI.Selection import ISelectionFilter
from Autodesk.Revit.UI.Selection import ObjectType

gdict = globals()
uiapp = revit
uidoc = uiapp.ActiveUIDocument
xamlfile = script.get_bundle_file(‘dialog/dialog.xaml’)

class CustomISelectionFilter(ISelectionFilter):
def init(self, category_name):
self.category_name = category_name

def AllowElement(self, e):
return True

def AllowReference(self, ref, point):
return True

class MyWindow(Windows.Window):
def init(self):
# self is the instance of the class and we are loading xaml file into that instance
wpf.LoadComponent(self, xamlfile)

def step(self, sender, args):
pass

def parseOptions(self):
pass

def clear(self, sender, args):
pass

def TextBox_KeyDown(self, sender, args):
pass

def handle_command_string(self, sender, args):
pass

def dev(self, sender, args):
try:
self.Hide()
Pipe_Sel = uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter(“Pipes”), “Select a Pipe”)
self.Show()

except Exception:
  print("Operation canceled", "Canceled by the user")

def build(self, sender, args):
pass

MyWindow().ShowDialog()

Hi,
you mix two different options:

  1. self.dialog.Show()
  2. self.dialog.ShowDialog()

self.dialog.Show() - modeless form. You have to use external event handler and import all the stuff explicitly inside a definition that you run via external event handler.

Or just stick to ShowDialog() :slight_smile:

please see this post Need help with my first xaml file - #6 by hoss53

I just need one working :).
Judging from your emjoi, the second should be easier.
But… The following gives an exception on the second click.
If anyone can find what is wrong, would be great. Otherwise any pointers on how to implement the modeless approach would be great. (If anyone knows how to do it, as a small, paid project, please contact myself: oded@formx.com)

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Formx" Width="400" Height="600" Padding="140,1,4,4">
  <Button Content="Dev" Click="dev"/>
</Window>
from Autodesk.Revit.UI.Selection import ISelectionFilter
from Autodesk.Revit.UI.Selection import ObjectType

gdict = globals()
uiapp = __revit__
uidoc = uiapp.ActiveUIDocument
xamlfile = script.get_bundle_file('dialog/small_dialog.xaml')

class CustomISelectionFilter(ISelectionFilter):
  def AllowElement(self, e):
      return True

  def AllowReference(self, ref, point):
    return True

class MyWindow(Windows.Window):
  def __init__(self):
    wpf.LoadComponent(self, xamlfile)

  def dev(self, sender, args):
    try:
      self.Hide()
      uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter(), "Select")
      self.Show()

    except Exception as inst:
      print(inst)

  def build(self, sender, args):
    pass

MyWindow().ShowDialog()

The exception on the second click is: name 'uidoc' is not defined

Have you tried

 def dev(self, sender, args):
    try:
      self.Hide()
      uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter(), "Select")
      self.ShowDialog() # <<< Here is the issue :)

    except Exception as inst:
      print(inst)

As Tomasz said?

:two_hearts: you guys.

For the future developer, here is a complete working solution:

xamlfile = script.get_bundle_file('dialog.xaml')

class CustomISelectionFilter(ISelectionFilter):
  def AllowElement(self, e):
      return True

  def AllowReference(self, ref, point):
    return True

class MyWindow(Windows.Window):
  def __init__(self):
    wpf.LoadComponent(self, xamlfile)

  def dev(self, sender, args):
    try:
      self.Hide()
      uidoc.Selection.PickObject(ObjectType.Element, CustomISelectionFilter(), "Select")
      self.ShowDialog() 

    except Exception as inst:
      print(inst)

  def build(self, sender, args):
    pass

MyWindow().ShowDialog()`Preformatted text`