How to access View Template Properties for Revit and compare them in Real Time? - view

I am trying to list the view template’s properties so we can compare them with another old template.
For example what model elements are hidden or have overrides in a given template or which Revit links have been hidden or overridden in a given template.
View Template
(https://www.google.com/search?q=view+template+revit&rlz=1C1GGRV_enUS770US770&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjLndrd2cTbAhVESq0KHX1cAPwQ_AUICygC&biw=1536&bih=824#imgrc=Q0v-pV7Nxl4kfM:)
I’m looking to devise a View Template Compare tool and access to the owner and creator of them.
public void ApplyViewTemplateToActiveView()
{
Document doc = this.ActiveUIDocument.Document;
View viewTemplate = (from v in new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
where v.IsTemplate == true && v.Name == "MyViewTemplate"
select v)
.First();
using (Transaction t = new Transaction(doc,"Set View Template"))
{
t.Start();
doc.ActiveView.ViewTemplateId = viewTemplate.Id;
t.Commit();
}
}
With Revit API you can access with:
GetTemplateParameterIds Method / ViewTemplateId Property

The Revit API exposes almost all the ViewTemplate properties.
For instance this method returns all the Visibility/Graphic Overrides for a specific category:
https://apidocs.co/apps/revit/2019/ed267b82-56be-6e3b-0c6d-4de7df1ed312.htm
The only thing I couldn't get for a ViewTemplate are the "includes", but all the rest seems to be there.
Update:
The list or properties "not included" can be retrieved with GetNonControlledTemplateParameterIds().

Yes, and no.
Yes, I guess you can use Forge Model Derivative API to export RVT file and then build a dashboard around the View Templates data. That's assuming that View Templates data actually gets exported when the model is translated. That data is not attached to any geometry so I would not be surprised if it was skipped. The question here is why? This is like renting a 16-wheel truck to move a duffel bag across the street.
No, if your intention is to directly interact with the RVT model. Forge can view it, but to push anything back or request changes to the model, is not available yet. Then again, I am not even sure that the view template data is available via model derivative exports.
This brings me another alternative. Why not just collect the data using Revit API, the standard way and then push it out to a Database and build on top of that? There is no reason to employ Forge for any of that.

Thanks Jeremy, I had dig into your amazing website and also some solution that Konrad post in the Dynamo Forum about this. In Revit seems pretty achievable, you filter the View that is View Template and then extracts these properties, is it correct?.
I am wondering if someone can point me in the right direction with Forge.
Some amazing guys are developing a BQL https://www.retriever.works/.
BQL(Building Query Language) is a query language for buildings, similar to how SQL is a query language for databases. It is fast and flexible. BQL helps improve efficiency for QA/QC (quality assurance and quality control), and building data extraction without leaving Revit. I am also trying these and I would like to understand if there are some works where I could start with Forge next week about this.

Related

Umbraco 8 - Get Children Of Node Using ContentAtXPath() Method

I've been refactoring an existing Umbraco project to use more performant querying when getting back document data as everything was previously being returned using LINQ. I have been using a combination of Umbraco's querying via XPaths and Examine.
I am currently stumped on trying to get child documents using the Umbraco.ContentAtXPath() method. What I would like to do is get child document based on a path I parse to the method. This is what I have currently:
IEnumerable<IPublishedContent> umbracoPages = Umbraco.ContentAtXPath("//* [#isDoc]/descendant::/About [#isDoc]");
Running this returns a "Object reference not set to an instance of an object." error and unable to see exactly where I'm going wrong (new to this form of querying in Umbraco).
Ideally, I'd like to enhance the querying to also carry out sorting using the non-LINQ approach, as demonstrated here.
Up until Umbraco 8, content was cached in an XML file, which made XPath perfect for querying content efficiently. In v8, however, the so called "NuCache" is not file based nor XML based, so the XPath query support is only there for ... well... Old times sake, I guess? Either way it's probably not going to be super efficient and (I'd advise) not something to "aim for". That said I of course don't know what you are changing from (Linq can be a lot of things) :-/
It certainly depends on how big your dataset is.
As Umbraco has moved away from the XML backed cache, you should look into Linq queries against your content models. Make sure you use ModelsBuilder to generate the models.
On a small dataset Linq will be much quicker than examine. On a large dataset Examine/Lucene will be much more steady on performance.
Querying NuCache is pretty fast in Umbraco 8, only beaten by an Examine search.
Assuming you're using Models Builder, and your About page is a child of Home page, you could use:
var homePage = (HomePage) Model.Root();
var aboutPage = homePage?.Children<AboutPage>().FirstOrDefault();
var umbracoPages = aboutPage.Children();
Where HomePage is your home page Document Type Alias and AboutPage is your About page Document Type alias.

Apply a sort to a dataset in a PowerApps component (PCF)

I’m trying to create a new dataset type Powerapps Component (PCF). For the moment I am using it to display a view of the records that are available in an entity in Microsoft Dynamics CRM.
I wish to make the view sort itself when I click on the grid column headers (in a similar way that the default CRM grid view does). I'm trying to figure out how to apply a sort to the dataset so that I can refresh it as indicated by the documentation for the dataset.refresh() function:
Refreshes the dataset based on filters, sorting, linking, new column.
New data will be pushed to control in another 'updateView' cycle.
The dataset object does have a “sorting” property, but changing its value and then refreshing the dataset doesn’t seem to have any effect. After the refresh, the sorting property reverts to the value it had before I changed it.
In short, the click handler for the grid header does something like the following bit of code. The refresh gets done and my updateView() function gets called as expected but the sorting was not applied.
dataset.sorting = [{name: 'createdon', sortDirection: 1}];
dataset.refresh();
Any help on getting the dataset sorting to work would be appreciated.
I've been experimenting with PowerApps Component Framework a little bit recently and I can confirm that the following code won't be working:
dataSet.sorting = [ { name: "columnName", sortDirection: 0 } ];
However, I managed to get this one working for me:
dataSet.sorting.pop(); // you may want to clean up the whole collection
dataSet.sorting.push({ name: "columnName", sortDirection: 0 });
I haven't really figured out the reason of this behavior. The sorting array may be implemented as some form of observable collection in the background.
I hope this will guide you to a functioning solution.
The documentation is pretty abysmal here, but here is my best guess from putting a few different pieces of information together.
TLDR: I think there is some kind of extra method that needs to be called on the .sorting property, but I can't find out what it is called. Maybe something like:
dataset.sorting.setSorting({name: 'createdon', sortDirection: 1});
I think you're going to have to try a bunch of likely method names and see what works.
Background and links:
The only reference I could find to dataset.sorting was from here:
In this preview for canvas apps, only a limited set of filtering and sortStatus methods are supported. Filter and sort can be applied to dataset on primary type columns except for the GUID. Filter and sorting can be applied in the same way as in model-driven apps.To retrieve the dataset with filtering and sorting information, call
the methods in context.parameters.[dataset_property_name].filtering
and context.parameters.[dataset_property_name].sorting, then invoke
the context.parameters.[dataset_property_name].refresh().
So it seems that the .filtering and .sorting properties are handled similarly, and that there are some methods attached to them, and only some are supported. That is about as vague as they could make it...
I did find an example of how .filtering is used:
_context.parameters.sampleDataset.filtering.setFilter({
conditions: conditionArray,
filterOperator: 1, // Or
});
There is a brief reference to .setFilter() in the docs, as well as FilterExpression
There is a SortStatus reference, but it doesn't have any corresponding methods explicitly called out. It is possible that this is not yet a supported feature in the public preview, or the documentation is lacking and the name and syntax of the method you need to call on .sorting is not yet documented.

Sitefinity: Where can I find the master GUID for a content item?

I'm building a web service for a client that pulls data from the Sitefinity CMS. The problem is they want to pass in a Guid for the service and receive the info about this item. No problem except I only have been able to locate the "live" Guid for one Item (and that was by combing through the HTML in the back end).
I was going to look at the tables in SQL Server but I'm not sure which table to look at. The content items have several tables all related of course and there isn't any documentation on how to look at this. I can find plenty of documentation on querying the master Guid, but no place to find it.
Oh, and these are custom content types built by the Module Builder.
Any Help would be SOOOOO appreciated!
var master = DynamicModuleManager.GetManager().Lifecycle.GetMaster(<liveGuidHere>);
One of the biggest consumers of Sitefinity webservices is Sitefinity. The best place to start looking for that guid is to take a look at what web service calls are being made when you pull up your custom content item list in the backend. I used the chrome developer tools and check in the network tab.
One I found for a stores module made with module builder was something to the effect of http://www.testsite.com/Sitefinity/Services/DynamicModules/Data.svc/?managerType=Telerik.Sitefinity.DynamicModules.DynamicModuleManager&providerName=OpenAccessProvider&itemType=Telerik.Sitefinity.DynamicTypes.Model.Stores.Store&provider=OpenAccessProvider&sortExpression=LastModified%20DESC&skip=0&take=50
The json this returns is a list of all the masters with their ids (note in the list that the content items all have have a status of 0) http://www.sitefinity.com/documentation/documentationarticles/developers-guide/sitefinity-essentials/modules/content-lifecycle
When you go to Administration / Module Builder / Your Module, you will see a link to the API on the top right corner.
This link goes to a page full of API examples for your particular module which is kind of cool.
Basically you would have to find your item first using LINQ and the GetValue extension method.
Once you have the item you can get its ID or any other property.
using Telerik.Sitefinity.Utilities.TypeConverters;
using Telerik.Sitefinity.DynamicModules;
using Telerik.Sitefinity.Model;
....
var mgr = DynamicModuleManager.GetManager();
var countrymasters = from ctry in mgr.GetDataItems(TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Destinations.Destination"))
where ctry.GetValue<string>("culture") == siteid &&
(ctry.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live && ctry.Visible == true)
select new
{
airport_cd = ctry.GetValue<string>("airport_cd"),
country_master_cd = ctry.GetValue<string>("country_master_cd")
};

Moving SP-Linq queries from test site to production site

I see articles on using SPMetal to generate the .cs file that allows LINQ to work properly. The file I'm talking about inherits from the Microsoft.SharePoint.Linq.DataContext class. How can I use LINQ without recompiling on my production environment, since I would need to regenerate this file using SPMetal on my production environment? I suspect the answer is going to be "can't do it".
I guess I'll use a CAML query instead unless there is some easier way to use LINQ that I am missing.
If the objective is just to query lists using LINQ and you want to avoid such recompilations, do not use SPMetal.
LINQ can be directly used on SPListItemCollection
e.g.
var FindCustomer = from SPListItem Item in Customers.Items
where Item["Orders"] as int == 5
select Item;
//or select new{Title = Item["Title"]}
This does not have hard coded entities but is more flexible. And as long as your list column names remain same, code can be deployed on any environment even if other lists are changing.
Also you can choose to retrieve few chosen field's data instead of retrieving data of all the fields every time.
There is no problem I guess. Personally I have been using Linq for good amount of time. I never generated the cs specifically for production. Is your site different across environments?
Im not sure if I'm missing the point or not, but the DataContext object takes the URL as apart of the constructor, so you should retrieve the URL from config somewhere E.g. database
DataContext teamSite = new DataContext("http://MarketingServer/SalesTeam");
OR use the SPContext object, if your code has a SharePoint context. E.g. in a web part
DataContext teamSite = new DataContext(SPContext.Current.Web.Url);

CakePHP, organize site structure around groups

So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?

Resources