private void Window_Loaded(object sender, RoutedEventArgs e) { //Lists to store the ElementId of Views placed on sheets List <ElementId> LegendsPlacedIds = new List <ElementId>(); List <ElementId> SchedulesPlacedIds = new List <ElementId>(); List <ElementId> ViewTemplatesUsedIds = new List <ElementId>(); List <View> RootViews = new List <View>(); try { //Get all sheets using a Filtered Element Collector foreach (ViewSheet sheet in new FilteredElementCollector(doc).OfClass(typeof(ViewSheet))) { //Get each view on each sheet and store them in the applicable list foreach (ElementId elementId in sheet.GetAllPlacedViews()) { //Cast the Element to a View View v = doc.GetElement(elementId) as View; if (v.ViewType == ViewType.Legend) { //For items like Legends and Schedules, we just need one instance so check if the list already //contains the Element Id if (!LegendsPlacedIds.Contains(elementId)) { //If the Legend container List doesn't already contain the Element Id, add it LegendsPlacedIds.Add(elementId); } } } } //Collect all instances of schedules placed on a sheet foreach (ScheduleSheetInstance scheduleInstance in new FilteredElementCollector(doc).OfClass(typeof(ScheduleSheetInstance)).ToElements()) { //Check to see if the container list already has the Schedule Id //Note that you need to get the ScheduleId from the Schedule Instance if (!SchedulesPlacedIds.Contains(scheduleInstance.ScheduleId)) { //If the Schedule isn't in the list, add the Element Id for it to the palced List SchedulesPlacedIds.Add(scheduleInstance.ScheduleId); } } //Collect all Views in the Document and store them in an IList so we can iterate them multiple times IList <Element> AllDocumentViews = Helpers.Collectors.ByCategory(doc, BuiltInCategory.OST_Views); //Iterate All views to check certain criteria of each view foreach (View view in AllDocumentViews) { //Check to make sure the view is Not a View Template if (!view.IsTemplate) { //Check to see if the view has a ViewTemplate applied if (view.ViewTemplateId != ElementId.InvalidElementId) { //Check to see if the View Template placed list already has the Element Id if (!ViewTemplatesUsedIds.Contains(view.ViewTemplateId)) { //if it does have a view template, add it to the list ViewTemplatesUsedIds.Add(view.ViewTemplateId); } } //Check to make sure the view is not a Legend if (view.ViewType != ViewType.Legend) { //Check to see if the View has a viewport Sheet name or Number parameter if (string.IsNullOrEmpty(view.get_Parameter(BuiltInParameter.VIEWPORT_SHEET_NAME).AsString()) || string.IsNullOrEmpty(view.get_Parameter(BuiltInParameter.VIEWPORT_SHEET_NUMBER).AsString())) { //Need to make sure this view isn't a parent view with dependents. Often the dependent views are placed, but if you delete //the parent, the dependents are removed as well if (view.GetDependentViewIds().Count == 0) { //Add the view to the Master Container with the Custom ElementIdName class Views.Add(new ElementIdName() { Check = false, Name = view.Name, ElemId = view.Id }); } else { //Store all views that have dependents to check and see if they too can be deleted RootViews.Add(view); } } } else { //If it is a legend, check to see if it is placed if (!LegendsPlacedIds.Contains(view.Id)) { //Add it to the list if not place Legends.Add(new ElementIdName() { Check = false, Name = view.Name, ElemId = view.Id }); } } } } //We have to iterate the views again after we have caught all the applied View templates above //to make sure we know which are not being used foreach (View view in AllDocumentViews) { //Make sure we only get View Templates if (view.IsTemplate) { //If it is a view template, check to see if it is in the Placed list if (!ViewTemplatesUsedIds.Contains(view.Id)) { //If not, add it to the master container with the Custom ElementIdName class ViewTemplates.Add(new ElementIdName() { Check = false, Name = view.Name, ElemId = view.Id }); } } } //Iterate through all Root views that had dependents foreach (View RootView in RootViews) { //Use a bool to be the switch if any dependent is placed bool placed = false; //Iterate each ViewId of each dependent foreach (ElementId viewId in RootView.GetDependentViewIds()) { //Use the Element Id to get the view associated View view = doc.GetElement(viewId) as View; //Check to see if the View has a viewport Sheet name or Number parameter if (!string.IsNullOrEmpty(view.get_Parameter(BuiltInParameter.VIEWPORT_SHEET_NAME).AsString()) || !string.IsNullOrEmpty(view.get_Parameter(BuiltInParameter.VIEWPORT_SHEET_NUMBER).AsString())) { //If ANY of the views along the way have this information, we don't want to delete the Root view //so make the bool true placed = true; } } //Check the bool variable and add the Root view only if none of the dependents were placed if (!placed) { //Add the view to the Master Container with the Custom ElementIdName class Views.Add(new ElementIdName() { Check = false, Name = RootView.Name, ElemId = RootView.Id }); } } //Collect all Schedules in the project IList <Element> AllSchedules = new FilteredElementCollector(doc).OfClass(typeof(ViewSchedule)).ToElements(); foreach (ViewSchedule Schedule in AllSchedules) { //check to make sure it is not a View Template schedule if (!Schedule.IsTemplate) { //Check to see if the view has a ViewTemplate applied if (Schedule.ViewTemplateId != ElementId.InvalidElementId) { //Check to see if the View Template placed list already has the Element Id if (!ViewTemplatesUsedIds.Contains(Schedule.ViewTemplateId)) { //if it does have a view template, add it to the list ViewTemplatesUsedIds.Add(Schedule.ViewTemplateId); } } //Make sure it is not a built in Title Block Revision Schedule becasue these can't be deleted if (!Schedule.IsTitleblockRevisionSchedule) { //Check to see if the Placed list contains the schedule if (!SchedulesPlacedIds.Contains(Schedule.Id)) { //If not, add it to the master container with the Custom ElementIdName class Schedules.Add(new ElementIdName() { Check = false, Name = Schedule.Name, ElemId = Schedule.Id }); } } } } //We have to iterate the views again after we have caught all the applied View templates above //to make sure we know which are not being used foreach (ViewSchedule Schedule in AllSchedules) { //Make sure we only get View Templates if (Schedule.IsTemplate && !Schedule.IsTitleblockRevisionSchedule) { //If it is a view template, check to see if it is in the Placed list if (!ViewTemplatesUsedIds.Contains(Schedule.Id)) { //If not, add it to the master container with the Custom ElementIdName class ViewTemplates.Add(new ElementIdName() { Check = false, Name = Schedule.Name, ElemId = Schedule.Id }); } } } //Set the Tab header text to include the number of items. just a visual touch, doesnt do anything TabViewTemplates.Header = "View Templates (" + ViewTemplates.Count + ")"; TabViews.Header = "Views (" + Views.Count + ")"; TabLegends.Header = "Legends (" + Legends.Count + ")"; TabSchedules.Header = "Schedules (" + Schedules.Count + ")"; //Set the Item source for the 4 different list views to the Master Containers ListViewViews.ItemsSource = Views; ListViewViewTemplates.ItemsSource = ViewTemplates; ListViewSchedules.ItemsSource = Schedules; ListViewLegends.ItemsSource = Legends; //Use a collection view on the item source of the list view to sort the items CollectionView ViewsSort = (CollectionView)CollectionViewSource.GetDefaultView(ListViewViews.ItemsSource); //We are using the "Name" column / property to sort in this case ViewsSort.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); } //Catch any exceptions thrown and provide the user with the information catch (Exception ex) { TaskDialog.Show("View Checking Error", ex.ToString()); } }