Hello! I would like to ask a follow up question on this thread Window WPF with work in Revit - #7 by c.poupin
Can you please tell me if I can make each element I select in the dropdown list immediately isolated? With the help
“uidoc.ActiveView.IsolateElementTemporary(itemId)” after
“uidoc.Selection.SetElementIds(ListElementId)”
it was possible to do this, but it is not possible to write in the code so that the view is restored back before pressing the next element.
And one more question. Please tell me how to make the winform window always on top of the Revit window?
P.S. Friends, it turned out to alternately isolate elements by writing “uidoc.ActiveView.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate)” before these two lines.
I will be grateful for the answer to the second question.
You have to create function that will be executed when SelectionChanged of dropdown triggered. In that function first of all uidoc.ActiveView.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate)
and then uidoc.ActiveView.IsolateElementTemporary(itemId)
In init method of class => dropdown.SelectionChanged += your function
if you want to make the wpf always on top, you can add
Topmost=“True”
inside
<windows>
Thanks friends for the tip. Since I’m a beginner in Windows Forms, I didn’t really understand this “dropdown.SelectionChanged += your function”… But I managed to do what I was looking for in a different way. Special thanks for Topmost, it helped! I also had a few new questions about the same script. So I understand it’s better to create a new topic than to ask them here? For now, I’ll ask, if there are tips to move, I’ll create a new topic.
It turned out to make a drop-down list with two elements that, when selected in the table, are isolated and scaled in the center of the screen. But now, with any revit command or escape key, the view is restored to the original without any isolated elements.
As far as I understand - the reason is the absence of a transaction - Revit does not execute the isolation of elements as a command. Is it possible to somehow correctly register a transaction here for executing commands with Revit?
import clr
import sys
import System
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\DLLs')
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('DSCoreNodes')
import DSCore
#import net library
from System.Collections.Generic import List
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)
rpt = DSCore.List.OfRepeatedItem
tsp = DSCore.List.Transpose
try:
clr.AddReference("IronPython.Wpf")
clr.AddReference('System.Core')
clr.AddReference('System.Xml')
clr.AddReference('PresentationCore')
clr.AddReference('PresentationFramework')
except IOError:
raise
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
import wpf
cats = doc.Settings.Categories
catsN = sorted([c.Name for c in cats])
lst1 = []
walls_1 = UnwrapElement(FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(Wall).ToElements())
floors_1 =UnwrapElement(FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(Floor).ToElements())
c1 = [i for i in cats if i.Name == "Structural Columns"][0]
bc1 = System.Enum.ToObject(BuiltInCategory, c1.Id.IntegerValue)
columns_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc1).WhereElementIsNotElementType().ToElements()
c2 = [i for i in cats if i.Name == "Structural Framing"][0]
bc2 = System.Enum.ToObject(BuiltInCategory, c2.Id.IntegerValue)
framing_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc2).WhereElementIsNotElementType().ToElements()
c3 = [i for i in cats if i.Name == "Structural Foundations"][0]
bc3 = System.Enum.ToObject(BuiltInCategory, c3.Id.IntegerValue)
foundations_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc3).WhereElementIsNotElementType().ToElements()
c4 = [i for i in cats if i.Name == "Ceilings"][0]
bc4 = System.Enum.ToObject(BuiltInCategory, c4.Id.IntegerValue)
ceilings_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc4).WhereElementIsNotElementType().ToElements()
c5 = [i for i in cats if i.Name == "Walls"][0]
bc5 = System.Enum.ToObject(BuiltInCategory, c5.Id.IntegerValue)
walls_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc5).WhereElementIsNotElementType().ToElements()
c6 = [i for i in cats if i.Name == "Floors"][0]
bc6 = System.Enum.ToObject(BuiltInCategory, c6.Id.IntegerValue)
floors_1 = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(bc6).WhereElementIsNotElementType().ToElements()
inter1 = []
for i in walls_1:
k = [i,FilteredElementCollector(doc).OfCategory(bc6).WherePasses(ElementIntersectsElementFilter(i)).ToElements()]
inter1.append(k)
inter2 = [[rpt(i[0],len(i[1])),i[1]] for i in inter1]
inter3 = [tsp(i) for i in inter2]
inter4 = [i1[0] for i in inter3 for i1 in i]
inter5 = [i1[1] for i in inter3 for i1 in i]
class MyForm(Window):
LAYOUT = """
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2"
Width="650"
Topmost="True"
Height="700">
<Grid>
<Label
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="14,16,0,00"
Width="130"
Height="29"
x:Name="ClickSelect"
Content="Click to Select" />
<Button
Content="Close"
Grid.Column="2"
Grid.Row="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,16,16"
Width="96"
Height="24"
x:Name="button1"
Click="button1_Click" />
<ListBox
x:Name="listBox1"
SelectionChanged="listBox0_SelectionChanged"
Grid.Row="1"
Grid.Column="0"/>
<ListBox
x:Name="listBox0"
SelectionChanged="listBox1_SelectionChanged"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="1"/>
<ListBox
x:Name="listBox2"
SelectionChanged="listBox2_SelectionChanged"
Grid.Row="1"
Grid.Column="2"
Grid.ColumnSpan="1"/>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="160 px" />
<ColumnDefinition
Width="160" />
<ColumnDefinition
Width="180" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition
Height="50 px" />
<RowDefinition
Height="500" />
<RowDefinition
Height="100" />
</Grid.RowDefinitions>
</Grid>
</Window>"""
def __init__(self):
self.ui = wpf.LoadComponent(self, StringReader(MyForm.LAYOUT))
for i,j in zip(inter4,inter5):
item = System.Windows.Controls.ListBoxItem()
item.Content = i.Name
item.Tag = i.Id
self.ui.listBox1.Items.Add(item)
item1 = System.Windows.Controls.ListBoxItem()
item1.Content = j.Name
item1.Tag = j.Id
self.ui.listBox0.Items.Add(item1)
item2 = System.Windows.Controls.ListBoxItem()
item2.Content = [i,j]
item2.Tag = [i.Id,j.Id]
self.ui.listBox2.Items.Add(item2)
def button1_Click(self, sender, e):
self.Close()
def listBox0_SelectionChanged(self, sender, e):
itemId = self.ui.listBox0.SelectedItem.Tag
def listBox1_SelectionChanged(self, sender, e):
itemId = self.ui.listBox0.SelectedItem.Tag
def listBox2_SelectionChanged(self, sender, e):
itemId = self.ui.listBox2.SelectedItem.Tag
print((self.ui.listBox2.SelectedItem.Tag))
elem = [doc.GetElement(i) for i in itemId]
uidoc.ActiveView.DisableTemporaryViewMode(TemporaryViewMode.TemporaryHideIsolate)
uidoc.Selection.SetElementIds(List[ElementId](itemId))
uidoc.ActiveView.IsolateElementsTemporary(List[ElementId](itemId))
uidoc.RefreshActiveView()
uidoc.GetOpenUIViews()[0].ZoomToFit()
form = MyForm()
form.Show()
Is it even possible to inject a transaction into the body of a function in a class? It doesn’t work and gives me an error
no,
a workaround is to implement an IExternalEventHandler Interface
some examples
Otherwise, without transaction, instead of isolating the element, you can zoom in on it with uidoc.ShowElements()
Thanks for the links! I will study, I think that I need the first scenario. I just need to figure it out. Might be able to come up with something.