I am trying to use a filter to show/hide a certain element on the view. The family is from catogary GenericModel. I use the same code snippet that on the help on the autodesk site it works fine in its original state (catogary is walls) but when I changed it to GenericModel I got the following error:
"One of the given rules refers to a parameter that does not apply to this filter's categories."
I suspect that something wrong with the typeOf(FamilyInstance).
The original code on Autodesk site is:
http://help.autodesk.com/view/RVT/2014/ENU/?guid=GUID-B6FB80F2-7A17-4242-9E95-D6056090E85B
and here is my code
Transaction trans = new Transaction(doc);
trans.Start("Hide_or_Unhide");
//
List<ElementId> categories = new List<ElementId>();
categories.Add(new ElementId(BuiltInCategory.OST_GenericModel));
ParameterFilterElement parameterFilterElement = ParameterFilterElement.Create(doc, "elementNo = 102", categories);
FilteredElementCollector parameterCollector = new FilteredElementCollector(doc);
Parameter parameter = parameterCollector.OfClass(typeof(FamilyInstance)).FirstElement().get_Parameter("elementNo");
List<FilterRule> filterRules = new List<FilterRule>();
filterRules.Add(ParameterFilterRuleFactory.CreateEqualsRule(parameter.Id, 102));
try
{
parameterFilterElement.SetRules(filterRules);
}
catch (Exception ex)
{
TaskDialog.Show("", ex.Message);
}
OverrideGraphicSettings filterSettings = new OverrideGraphicSettings();
// outline walls in red
filterSettings.SetProjectionLineColor(new Autodesk.Revit.DB.Color(255, 0, 0));
Autodesk.Revit.DB.View curView = doc.ActiveView;
curView.SetFilterOverrides(parameterFilterElement.Id, filterSettings);
trans.Commit();
I think the problem is that your code which is performing the FilteredElementCollector is not specific enough. In the ADN sample, they're filtering on a type of "Wall" - but you're filtering on a type of FamilyInstance. You're correct on the type, but FamilyInstance covers lots of categories. The FirstElement() is giving the first FamilyInstance in the collector (which is likely not a generic model).
Try this line:
Parameter parameter = parameterCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_GenericModel).FirstElement().get_Parameter("elementNo");
That way, you should get the first element that is both a family instance AND a GenericModel.
Good Luck,
Matt
Related
I am trying to run code from the Autodesk help
http://help.autodesk.com/view/RVT/2014/ENU/?guid=GUID-B6FB80F2-7A17-4242-9E95-D6056090E85B
private void CreateViewFilter(Autodesk.Revit.DB.Document doc, View view)
{
List<ElementId> categories = new List<ElementId>();
categories.Add(new ElementId(BuiltInCategory.OST_Walls));
ParameterFilterElement parameterFilterElement =
ParameterFilterElement.Create(doc, "Comments = foo", categories);
FilteredElementCollector parameterCollector = new FilteredElementCollector(doc);
Parameter parameter = parameterCollector.OfClass(typeof(Wall)).FirstElement().get_Parameter("Comments");
List<FilterRule> filterRules = new List<FilterRule>();
filterRules.Add(ParameterFilterRuleFactory.CreateEqualsRule(parameter.Id, "foo", true));
parameterFilterElement.SetRules(filterRules);
OverrideGraphicSettings filterSettings = new OverrideGraphicSettings();
// outline walls in red
filterSettings.SetProjectionLineColor(new Color(255, 0, 0));
view.SetFilterOverrides(parameterFilterElement.Id, filterSettings);
}
When I open a view and run the code more than once, I get the following error
Revit encounterd a argumentException. The given value for name is already in use as a filter element name parmeter name: name at ParameterFilterElement parameterFilterElement = ParameterFilterElement.Create(doc, "Comments= foo", categories). I can't see where this happened in the code.(OBS I change the get_parameter to lookupparameter in the original code above because the first is deprecated)
According to the docs, the second parameter to the Create method is name. The error message states that you are already using the name "Comments = Foo". So I think your best bet is to dynamically generate the name or provide a way for a user to specify the name.
After a little bit thinking I get it. Actually I should do that from the beginging. Anyway the prgram create filter and It is now in the view so when I run the command again there is already one. Thank you.
I am trying to run the code that on the Autodesk help
http://help.autodesk.com/view/RVT/2014/ENU/?guid=GUID-B6FB80F2-7A17-4242-9E95-D6056090E85B
but it seem not to work. The code "FirstElement
().get_Parameter("Comments");"
don't work. No such function.
I got the following error:
Revit encoutered a System.MissingMethodException; Method not found:'AutoDesk.Revit.DB.Parameter Autodesk.Revit.DB.Element.get_Parameter(System.String)
What is the wrong with this code?
private void CreateViewFilter(Autodesk.Revit.DB.Document doc, View view)
{
List<ElementId> categories = new List<ElementId>();
categories.Add(new ElementId(BuiltInCategory.OST_Walls));
ParameterFilterElement parameterFilterElement =
ParameterFilterElement.Create(doc, "Comments = foo", categories);
FilteredElementCollector parameterCollector = new FilteredElementCollector
(doc);
Parameter parameter = parameterCollector.OfClass(typeof(Wall)).FirstElement
().get_Parameter("Comments");
List<FilterRule> filterRules = new List<FilterRule>();
filterRules.Add(ParameterFilterRuleFactory.CreateEqualsRule
(parameter.Id, "foo", true));
parameterFilterElement.SetRules(filterRules);
OverrideGraphicSettings filterSettings = new OverrideGraphicSettings();
// outline walls in red
filterSettings.SetProjectionLineColor(new Color(255, 0, 0));
view.SetFilterOverrides(parameterFilterElement.Id, filterSettings);
}
I guess you are using a version of Revit different from the help version (2014) ?
I think get_Parameter is deprecated since a couple of versions.
You can try with LookupParameter :
...FirstElement().LookupParameter("Comments");
or eventually GetParameters, but careful, this one returns a collections :
...FirstElement().GetParameters("Comments");
(The links refer to the last version but you can easily check for another one on the same site, and the 2 methods looks unchanged since Revit 2015.)
So, I'm writing an app to 'flesh out' new clients in Rally. It will have tools to create templates which will add first:
add a 'Feature'
add 'UserStories' under that 'Feature'
add 'Tasks' under those 'UserStories' individually
I have figured out step 1. But how to associate anything I can't figure out from the horrible and cryptic documentation. Here's what I have so far:
var FeatureToAdd = _featureRepository.GetFeatures().FirstOrDefault(x => x.Id == 2);
// Initialize the REST API. You can specify a web service version if needed in the constructor.
RallyRestApi restApi = GetRallyRestApi();
//Create an item
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate["Name"] = FeatureToAdd.Name;
toCreate["Description"] = FeatureToAdd.Description;
// important to which this belongs, but I no ID I ever use works
//toCreate["Workspace"] = "/workspace/" + WebConfigurationManager.AppSettings["RallyAPIWorkspaceID"];
//toCreate["Project"] = "/project/XXXXX";
//toCreate["Iteration"] = "/iteration/XXXXXX";
// create feature - feature is under PortfolioItem
CreateResult createFeatureResult = restApi.Create("PortfolioItem/Feature", toCreate);
// scrape ID off the end of the reference
var pureId = createFeatureResult.Reference.Substring(createFeatureResult.Reference.LastIndexOf('/') + 1);
// add UserStories
foreach (UserStory u in FeatureToAdd.UserStories)
{
toCreate = new DynamicJsonObject();
toCreate["Name"] =u.Name;
toCreate["Description"] = u.Description;
toCreate["WorkProduct"] = "PortfolioItem/Feature/" + pureId;
//toCreate["WorkProduct"] = createFeatureResult.Reference;<- tried this too
// hierarchicalrequirement = UserStory
CreateResult createUserStoryResult = restApi.Create("hierarchicalrequirement", toCreate);
}
Running this creates both, but no association happens. I get a warning:
Ignored JSON element hierarchicalrequirement.WorkProduct during processing of this request.
Why did it arbitrarily ignore this?...
It ignored WorkProduct because WorkProduct is not a valid field on HierarchicalRequirement. The field you want to specify to set the feature parent of a story is called PortfolioItem.
toCreate["PortfolioItem"] = Ref.GetRelativeRef(createFeatureResult.Reference);
Also, object relationships are specified as in WSAPI as refs (/type/id) so you can just directly pass in the reference from the createFeatureResult.
Sorry you're finding the api to be frustrating. It definitely has some weird dark corners but once you use it a bit and get a feel for how the various domain objects are related I think you'll find it to be quite powerful and consistent.
I have created code that gathers a list of the existing "Line Styles" in Revit.
List<Category> All_Categories = doc.Settings.Categories.Cast<Category>().ToList();
Category Line_Category = All_Categories[1];
foreach (Category one_cat in All_Categories) { if (one_cat.Name == "Lines") { Line_Category = one_cat;} }
if (Line_Category.CanAddSubcategory)
{
CategoryNameMap All_Styles = Line_Category.SubCategories; List<string> Line_Styles = new List<string>();
foreach (Category one_category in All_Styles) { if (one_category.Name.Contains("CO_NAME")) {Line_Styles.Add(one_category.Name); } }
TaskDialog.Show(Line_Styles.Count.ToString() + " Current Line Styles", List_To_Dialog(Line_Styles));
}
This gets the list of line styles, but when I try:
Category New_Line_Style = Line_Category.NewSubCategory....
Visual Studio tells me there is no definition for NewSubCategory
Can anyone tell me how to make a new SubCategory of "Lines", or what I'm doing wrong in the above code?
NOTE: I discovered the main issue. I was attempting to add the sub category to my variable Line_Category (which is itself a category, which should be a parent). I had also attempted adding the sub category to All_Categories (which had been cast as a list and not a CategoryNameMap).
When I added a variable that was not cast, NewSubCategory became available. However, now I am unable to see how to set the line pattern associated with my new style -- the only example I've found online suggests using New_Line_Style.LinePatternId, but that is not in the list of available options on my new SubCategory. Is there some way to set the default pattern to be used when creating a new SubCategory?
Jeremy Tammik wrote a post about retrieving all the linestyles here: http://thebuildingcoder.typepad.com/blog/2013/08/retrieving-all-available-line-styles.html. That might help explain some of the linestyle category stuff in more detail.
Here's another good link asking the same question and how it was solved using VB: http://thebuildingcoder.typepad.com/blog/2013/08/retrieving-all-available-line-styles.html. Here's a C# version of the VB code that worked for a new linestyle:
UIApplication app = commandData.Application;
UIDocument uidoc = app.ActiveUIDocument;
Document ptr2Doc = uidoc.Document;
Category lineCat = ptr2Doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
Category lineSubCat;
string newSubCatName = "NewLineStyle";
Color newSubCatColor = new Color(255, 0, 0); //Red
try
{
using (Transaction docTransaction = new Transaction(ptr2Doc, "hatch22 - Create SubCategory"))
{
docTransaction.Start();
lineSubCat = ptr2Doc.Settings.Categories.NewSubcategory(lineCat, newSubCatName);
lineSubCat.LineColor = newSubCatColor;
docTransaction.Commit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
I'm trying to figure out how to get the currently opened document on Lotus Notes through C#, but I cannot. Even though I researched half a day on Google, I couldn't find anything useful.
With my code I get the view I want, the database I want, etc, but I just would like to get the opened document. I tried something like IsUIDocOpen, but none of the full collection contains it as true.
Does someone know if there is any different between an opened document and a non-opened document trough Domino API? My workaround is to get the subject of the email and the size of the email and compare each one and when it matches get the Entry ID and then get the information I need - but that takes too long, especially when the inbox is big.
Any suggestions?
Here is my code:
NotesSession session = new NotesSession();
session.Initialize(sPassword);
notedb = session.GetDatabase(server, filename, false);
if (notedb.IsOpen)
{
mailView = notedb.GetView("$Inbox");
mailDoc = mailView.GetLastDocument();
//mailDoc = mailView.GetDocumentByKey();
try
{
while (mailDoc != null)
{
NotesItem item = mailDoc.GetFirstItem("From");
if (item != null)
{
MessageBox.Show("From = " + item.Text);
}
}
}
}
Solution: should be something like: mailDoc = mailView.GetCurrentDocument(); // But obviously this method does not exist :D
=====================================================================================
Solution code:
Type NotesUIWorkspaceType = Type.GetTypeFromProgID("Notes.NotesUIWorkspace", true);
object workspace = Activator.CreateInstance(NotesUIWorkspaceType);
object uiDoc = NotesUIWorkspaceType.InvokeMember("CurrentDocument", BindingFlags.GetProperty, null, workspace, null);
Type NotesUIDocument = uiDoc.GetType();
object Subject = NotesUIDocument.InvokeMember("FieldGetText", BindingFlags.InvokeMethod, null, uiDoc, new Object[] { "Subject" });
string subject = "test";
NotesUIDocument.InvokeMember("FieldSetText", BindingFlags.InvokeMethod, null, uiDoc, new Object[] { "Subject", subject });
object Body = NotesUIDocument.InvokeMember("FieldGetText", BindingFlags.InvokeMethod, null, uiDoc, new Object[] { "Body" });
What you actually need is the Notes OLE classes.
The C# Interop classes are based on the Notes COM classes. The COM classes only have access to the "back end". I.e., the root object is Lotus.NotesSession, and all the classes work against data stored in .NSF files. They have no access to anything in the Notes UI.
The Notes OLE classes have access to both the "back end", with the root object Notes.NotesSession, and the "front end" with the root object Notes.NotesUIWorkspace. As you can tell by the name of that class, it's the front end classes that give you access to elements of the Notes client UI.
Note the subtle difference: the prefix for the OLE classes is "Notes.", instead of the prefix "Lotus." for the COM classes.
In old-style VB late binding, the OLE classes are instantiated this way:
CreateObject("Notes.NotesUIWorkspace")
I'm not sure how that translates into C#.
Anyhow, once you have the NotesUIWorkspace object, the currently opened document is available with the NotesUIWorkspace.CurrentDocument method.
IF you are using the Interop Classes you need to use NotesUIView.CurrentView.Documents to get what you want... see here.
You'll need to get the NotesUIWorkspace first, then use the CurrentDocument property
NotesUIWorkspace workspace = new NotesUIWorkspace();
NotesUIDocument uidoc = workspace.CurrentDocument();