├── .gitattributes ├── .gitignore ├── App └── BipChecker.addin ├── Command └── Command.cs ├── Inno_setup ├── Checker.ico └── Installer.iss ├── License.md ├── Model ├── BaseElement.cs ├── DialogUtils.cs ├── ExcelUtils.cs ├── IEnumerableUtils.cs ├── JsonUtils.cs ├── NotifyPropertyChanged.cs ├── ParameterData.cs ├── PraUtils.cs ├── RelayCommand.cs ├── RevitEvent.cs ├── StringUtils.cs └── WindowHandle.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── RevitElementBipChecker.csproj ├── RevitElementBipChecker.sln ├── View ├── MainWindows.xaml └── MainWindows.xaml.cs ├── Viewmodel ├── BipCheckerViewmodel.cs ├── CopyCommand.cs ├── ExportExcelCommand.cs ├── ExportJsonCommand.cs ├── PickFirstCommand.cs └── SelectedCommand.cs └── doc ├── GIWlYwW8wt.gif ├── Revit_HmBMFy23mM.png ├── Revit_dGgL1g5tq4.png ├── _Image_7f2dfd6b-9f5c-4732-9cb8-fb1e05c7c205.png ├── _Image_8818052f-5f71-46f9-8d4c-314997031280.png ├── _Image_d275515e-7661-4d53-aed8-6624fec689d9.png └── _Image_f1aac13a-394a-4b91-87d3-02ecf8bfd3ef.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Ignore thumbnails created by Windows 2 | Thumbs.db 3 | 4 | #Ignore files built by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | *.iref 23 | *.db 24 | *.ide 25 | *.opendb 26 | *.lock 27 | *.ide-shm 28 | *.ide-wal 29 | [Bb]in 30 | [Dd]ebug*/ 31 | *.lib 32 | *.sbr 33 | obj/ 34 | [Rr]elease*/ 35 | _ReSharper*/ 36 | [Tt]est[Rr]esult* 37 | .vs/ 38 | 39 | #Nuget packages folder 40 | packages/ 41 | 42 | 43 | -------------------------------------------------------------------------------- /App/BipChecker.addin: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Built-in Parameter Checker 5 | List all built-in parameters on selected element or its type 6 | RevitElementBipChecker.dll 7 | RevitElementBipChecker.Command.Command 8 | B83C55F1-7C4E-4DDD-B609-17FBEA21A137 9 | https://chuongmep.com/ 10 | https://chuongmep.com/ 11 | 12 | 13 | -------------------------------------------------------------------------------- /Command/Command.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using Autodesk.Revit.Attributes; 3 | using Autodesk.Revit.DB; 4 | using Autodesk.Revit.UI; 5 | using Autodesk.Revit.UI.Selection; 6 | using RevitElementBipChecker.Model; 7 | using RevitElementBipChecker.View; 8 | using RevitElementBipChecker.Viewmodel; 9 | 10 | namespace RevitElementBipChecker.Command 11 | { 12 | [Transaction(TransactionMode.Manual)] 13 | [Regeneration(RegenerationOption.Manual)] 14 | [Journaling(JournalingMode.UsingCommandData)] 15 | public class Command : IExternalCommand 16 | { 17 | public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) 18 | { 19 | UIApplication uiapp = commandData.Application; 20 | UIDocument uidoc = uiapp.ActiveUIDocument; 21 | Document doc = uidoc.Document; 22 | 23 | BipCheckerViewmodel vm = new BipCheckerViewmodel(uidoc); 24 | MainWindows frMainWindows = new MainWindows(vm); 25 | frMainWindows.WindowStartupLocation = WindowStartupLocation.CenterScreen; 26 | frMainWindows.SetRevitAsWindowOwner(); 27 | frMainWindows.Show(); 28 | return Result.Succeeded; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Inno_setup/Checker.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chuongmep/RevitElementBipChecker/41354474c22cd56409d968934b67c7751638d581/Inno_setup/Checker.ico -------------------------------------------------------------------------------- /Inno_setup/Installer.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define AppId "B83C55F1-7C4E-4DDD-B609-17FBEA21A137" 5 | #define AppName "RevitBipChecker" 6 | #define AppVersion "1.0.9" 7 | #define AppPublisher "ChuongHo" 8 | #define AppURL "http://chuongmep.com/" 9 | #define AppComments "Revit Bip Element Checker" 10 | #define BundleDirName "C:\ProgramData\Autodesk\Revit\Addins\2022" 11 | 12 | [Setup] 13 | ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. 14 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 15 | AppId={{AppId}} 16 | AppName={#AppName} 17 | AppVersion={#AppVersion} 18 | ;AppVerName={#MyAppName} {#MyAppVersion} 19 | AppPublisher={#AppPublisher} 20 | AppComments={#AppComments} 21 | AppPublisherURL={#AppURL} 22 | AppSupportURL={#AppURL} 23 | AppUpdatesURL={#AppURL} 24 | DefaultDirName={autopf}\{#AppName} 25 | DisableDirPage=yes 26 | DefaultGroupName={#AppName} 27 | DisableProgramGroupPage=yes 28 | ; Uncomment the following line to run in non administrative install mode (install for current user only.) 29 | ;PrivilegesRequired=lowest 30 | OutputBaseFilename="Revit Bip Checker Setup" 31 | Compression=lzma 32 | SolidCompression=yes 33 | WizardStyle=modern 34 | UninstallDisplayName={#AppName} 35 | ; ICON CONFIGURATION 36 | SetupIconFile=Checker.ico 37 | UninstallDisplayIcon={uninstallexe} 38 | [Languages] 39 | Name: "english"; MessagesFile: "compiler:Default.isl" 40 | 41 | [Files] 42 | ; Source: "C:\Program Files (x86)\Inno Setup 6\Examples\MyProg.exe"; DestDir: "{app}"; Flags: ignoreversion 43 | Source: "..\App\BipChecker.addin"; DestDir: "{#BundleDirName}"; Flags: ignoreversion 44 | Source: "..\bin\Debug\RevitElementBipChecker.dll"; DestDir: "{#BundleDirName}"; Flags: ignoreversion 45 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 46 | 47 | [Icons] 48 | Name: "{group}\{cm:UninstallProgram,{#AppName}}"; Filename: "{uninstallexe}" 49 | 50 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-Current by Jeremy Tammik, Autodesk Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Model/BaseElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Autodesk.Revit.DB; 7 | using Autodesk.Revit.UI; 8 | using RevitElementBipChecker.Viewmodel; 9 | 10 | namespace RevitElementBipChecker.Model 11 | { 12 | public class BaseElement : ViewmodeBase 13 | { 14 | private Element _element; 15 | private UIDocument _uiDoc; 16 | public BipCheckerViewmodel Viewmodel { get; set; } 17 | public UIDocument UIDoc 18 | { 19 | get => _uiDoc ; 20 | set => _uiDoc = value; 21 | } 22 | 23 | public Element Element 24 | { 25 | get => _element; 26 | set => _element = value; 27 | } 28 | 29 | private Element elementType; 30 | public Element ElementType 31 | { 32 | get 33 | { 34 | if(Element.CanHaveTypeAssigned()) return UIDoc.Document.GetElement(Element.GetTypeId()); 35 | return elementType; 36 | } 37 | set => elementType = value; 38 | } 39 | 40 | public string category; 41 | public string Category 42 | { 43 | get => Element.Category.Name; 44 | set => category = value; 45 | } 46 | 47 | public string Name 48 | { 49 | get => Element.Name; 50 | set => Element.Name = value; 51 | } 52 | public string State { get; set; } 53 | 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /Model/DialogUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Autodesk.Revit.UI; 8 | 9 | namespace RevitElementBipChecker.Model 10 | { 11 | public static class DialogUtils 12 | { 13 | /// 14 | /// Return Result Has Select Element Current Or Not 15 | /// 16 | /// Title Question 17 | /// 18 | public static bool QuestionMsg(string Caption) 19 | { 20 | 21 | var dialog = new TaskDialog(Caption); 22 | 23 | dialog.MainIcon = TaskDialogIcon.TaskDialogIconNone; 24 | dialog.MainInstruction = Caption; 25 | 26 | dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "Element Current"); 27 | dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "Element In RvtLinked"); 28 | 29 | return dialog.Show() == TaskDialogResult.CommandLink1; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Model/ExcelUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Threading.Tasks; 10 | 11 | namespace RevitElementBipChecker.Model 12 | { 13 | public static class ExcelUtils 14 | { 15 | /// 16 | /// Save Report To File Csv 17 | /// 18 | /// data table 19 | /// output path of file 20 | /// filename want save 21 | public static void OpenExcel(this DataTable dt, out string path, string filename = "Report.csv") 22 | { 23 | string PathDocument = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 24 | string namesave; 25 | if (filename.ToLower().Contains(".csv")) 26 | { 27 | namesave = filename; 28 | } 29 | else 30 | { 31 | namesave = filename + ".csv"; 32 | } 33 | path = Path.Combine(PathDocument, namesave); 34 | if (File.Exists(path)) 35 | { 36 | File.Delete(path); 37 | } 38 | var lines = new List(); 39 | 40 | string[] columnNames = dt.Columns 41 | .Cast() 42 | .Select(column => column.ColumnName) 43 | .ToArray(); 44 | 45 | var header = string.Join(",", columnNames.Select(name => $"\"{name}\"")); 46 | lines.Add(header); 47 | 48 | EnumerableRowCollection valueLines = dt.AsEnumerable() 49 | .Select(row => string.Join(",", row.ItemArray.Select(val => $"\"{val.ToString().FixUnitInch()}\""))); 50 | 51 | lines.AddRange(valueLines); 52 | 53 | File.WriteAllLines(path, lines,Encoding.UTF8); 54 | } 55 | 56 | /// 57 | /// convert Data Object to data table 58 | /// 59 | /// 60 | /// 61 | /// 62 | public static DataTable ToDataTable(this IList data) 63 | { 64 | PropertyDescriptorCollection props = 65 | TypeDescriptor.GetProperties(typeof(T)); 66 | DataTable table = new DataTable(); 67 | for(int i = 0 ; i < props.Count ; i++) 68 | { 69 | PropertyDescriptor prop = props[i]; 70 | table.Columns.Add(prop.Name, prop.PropertyType); 71 | } 72 | object[] values = new object[props.Count]; 73 | foreach (T item in data) 74 | { 75 | for (int i = 0; i < values.Length; i++) 76 | { 77 | values[i] = props[i].GetValue(item); 78 | } 79 | table.Rows.Add(values); 80 | } 81 | return table; 82 | } 83 | 84 | /// 85 | /// convert optimize data object to data table 86 | /// 87 | /// 88 | /// 89 | /// 90 | public static DataTable ToDataTable2(this IList data) 91 | { 92 | PropertyDescriptorCollection properties = 93 | TypeDescriptor.GetProperties(typeof(T)); 94 | DataTable table = new DataTable(); 95 | foreach (PropertyDescriptor prop in properties) 96 | table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); 97 | foreach (T item in data) 98 | { 99 | DataRow row = table.NewRow(); 100 | foreach (PropertyDescriptor prop in properties) 101 | row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; 102 | table.Rows.Add(row); 103 | } 104 | return table; 105 | } 106 | 107 | 108 | /// 109 | /// Decode Unicode 8 110 | /// 111 | /// 112 | /// 113 | public static string DecodeFromUtf8(this string utf8String) 114 | { 115 | // copy the string as UTF-8 bytes. 116 | byte[] utf8Bytes = new byte[utf8String.Length]; 117 | for (int i=0;i 13 | /// Convert From T IEnumerable To ObservableCollection 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static ObservableCollection ToObservableCollection(this IEnumerable source) 19 | { 20 | ObservableCollection newSource = new ObservableCollection(); 21 | foreach (T t in source) 22 | { 23 | newSource.Add(t); 24 | } 25 | 26 | return newSource; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Model/JsonUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Newtonsoft.Json; 9 | 10 | namespace RevitElementBipChecker.Model 11 | { 12 | public static class JsonUtils 13 | { 14 | public static void WriteJson(this DataTable dataTable, out string path, string filename = "Report.json") 15 | { 16 | string PathDocument = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 17 | string namesave; 18 | if (filename.ToLower().Contains(".json")) 19 | { 20 | namesave = filename; 21 | } 22 | else 23 | { 24 | namesave = filename + ".json"; 25 | } 26 | path = Path.Combine(PathDocument, namesave); 27 | if (File.Exists(path)) 28 | { 29 | File.Delete(path); 30 | } 31 | string serializeObject = JsonConvert.SerializeObject(dataTable,Formatting.Indented); 32 | File.WriteAllText(path, serializeObject); 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Model/NotifyPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.Reflection; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace RevitElementBipChecker.Model 8 | { 9 | public class ViewmodeBase : INotifyPropertyChanged 10 | { 11 | public event PropertyChangedEventHandler PropertyChanged; 12 | 13 | 14 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 15 | { 16 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 17 | } 18 | 19 | 20 | // 21 | /// Called when the specified property has been changed. 22 | /// 23 | /// Name of the property. 24 | /// The old value. 25 | /// The new value. 26 | protected virtual void OnPropertyChanged(string propertyName, object oldValue, object newValue) 27 | { 28 | this.OnPropertyChanged(propertyName); 29 | } 30 | 31 | #region Can Optimize 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public void OnPropertyChanged(ref T property, T value, [CallerMemberName] string propertyName = "") 40 | { 41 | property = value; 42 | var handler = PropertyChanged; 43 | if (handler != null) 44 | { 45 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 46 | } 47 | } 48 | 49 | #endregion 50 | 51 | /// 52 | /// Sets the property value. 53 | /// 54 | /// The type of the property. 55 | /// The field. 56 | /// The value. 57 | /// Name of the property. 58 | /// 59 | /// True if the property was set. 60 | /// 61 | /// This method uses the CallerMemberNameAttribute to determine the property name. 62 | protected bool SetValue(ref T field, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") 63 | { 64 | // ReSharper disable once RedundantNameQualifier 65 | if (object.Equals(field, value)) 66 | { 67 | return false; 68 | } 69 | this.VerifyProperty(propertyName); 70 | //// this.OnPropertyChanging(propertyName, field, value); 71 | T oldValue = field; 72 | field = value; 73 | this.OnPropertyChanged(propertyName, oldValue, value); 74 | return true; 75 | } 76 | 77 | /// 78 | /// Verifies the property name. 79 | /// 80 | /// Name of the property. 81 | [Conditional("DEBUG")] 82 | private void VerifyProperty(string propertyName) 83 | { 84 | var type = this.GetType(); 85 | 86 | // Look for a public property with the specified name. 87 | var propertyInfo = type.GetTypeInfo().GetDeclaredProperty(propertyName); 88 | 89 | Debug.Assert(propertyInfo != null, string.Format(CultureInfo.InvariantCulture, "{0} is not a property of {1}", propertyName, type.FullName)); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Model/ParameterData.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.Revit.DB; 2 | 3 | namespace RevitElementBipChecker.Model 4 | { 5 | public class ParameterData 6 | { 7 | public ParameterData(Parameter parameter,Document doc,bool isinstance=true) 8 | { 9 | this.Parameter = parameter; 10 | this.BuiltInParameter = (parameter.Definition as InternalDefinition).BuiltInParameter.ToString(); 11 | this.ParameterName = parameter.Definition.Name; 12 | this.Id = parameter.Id.ToString(); 13 | this.ParameterGroup = parameter.Definition.ParameterGroup.ToString(); 14 | this.ParameterType = parameter.GetParameterType(); 15 | this.GroupName = LabelUtils.GetLabelFor(parameter.Definition.ParameterGroup); 16 | this.Type = parameter.GetParameterType(); 17 | this.ReadWrite = parameter.IsReadWrite(); 18 | this.Value = parameter.GetValue(); 19 | this.StringValue = parameter.AsValueString() == null 20 | ? parameter.AsString() 21 | : parameter.AsValueString() ; 22 | this.Shared = parameter.Shared(); 23 | this.GUID = parameter.Guid(); 24 | this.TypeOrInstance = isinstance?"Instance":"Type"; 25 | this.AssGlobalPara = parameter.GetAssGlobalParameter(doc); 26 | this.AssGlobalParaValue = parameter.GetAssGlobalParameterValue(doc); 27 | } 28 | 29 | public Autodesk.Revit.DB.Parameter Parameter { get; set; } 30 | public string ParameterName { get; set; } 31 | public string Id { get; set; } 32 | public string TypeOrInstance { get; set; } 33 | public string BuiltInParameter { get; set; } 34 | public string Type { get; set; } 35 | public string ReadWrite { get; set; } 36 | public string Value { get; set; } 37 | public string StringValue { get; set; } 38 | public string ParameterGroup { get; set; } 39 | public string ParameterType { get; set; } 40 | public string GroupName { get; set; } 41 | public string Shared { get; set; } 42 | public string GUID { get; set; } 43 | 44 | public string AssGlobalPara { get; set; } 45 | public string AssGlobalParaValue { get; set; } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Model/PraUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Autodesk.Revit.DB; 10 | using Autodesk.Revit.UI; 11 | using RevitElementBipChecker.Viewmodel; 12 | using GlobalParameter = Autodesk.Revit.DB.GlobalParameter; 13 | 14 | namespace RevitElementBipChecker.Model 15 | { 16 | public static class PraUtils 17 | { 18 | 19 | public const string Caption = "Built-in Parameter Checker"; 20 | /// 21 | /// Return Element Selected 22 | /// 23 | /// 24 | /// 25 | public static List GetSelection(this UIDocument _uidoc) 26 | { 27 | Document doc = _uidoc.Document; 28 | List value = new List(); 29 | _uidoc.Selection.GetElementIds(); 30 | Type t = _uidoc.Selection.GetType(); 31 | if (t.GetMethod("GetElementIds") != null) 32 | { 33 | MethodInfo met = t.GetMethod("GetElementIds"); 34 | value = ((ICollection)met.Invoke(_uidoc.Selection, null)).Select(a => doc.GetElement(a)).ToList(); 35 | } 36 | else 37 | { 38 | value = ((System.Collections.IEnumerable)t.GetProperty("Elements").GetValue(_uidoc.Selection, null)).Cast().ToList(); 39 | } 40 | return value.OrderBy(x => x.Name).ToList(); 41 | } 42 | 43 | /// 44 | /// MessageBox wrapper for question message. 45 | /// 46 | public static bool QuestionMsg(string msg) 47 | { 48 | Debug.WriteLine(msg); 49 | 50 | var dialog = new TaskDialog(Caption); 51 | 52 | dialog.MainIcon = TaskDialogIcon.TaskDialogIconNone; 53 | dialog.MainInstruction = msg; 54 | 55 | dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "Instance parameters"); 56 | dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "Type parameters"); 57 | 58 | return dialog.Show() == TaskDialogResult.CommandLink1; 59 | } 60 | 61 | /// 62 | /// Return Real String Of Double 63 | /// 64 | /// 65 | /// 66 | public static string RealString(double a) 67 | { 68 | return a.ToString("0.##"); 69 | } 70 | 71 | /// 72 | /// Return type Of Parameter 73 | /// 74 | /// 75 | /// 76 | public static string GetParameterType(this Autodesk.Revit.DB.Parameter parameter) 77 | { 78 | #if R18 || R19 || R20 || R21 79 | ParameterType pt = parameter.Definition.ParameterType; // returns 'Invalid' for 'ElementId' 80 | string s = ParameterType.Invalid == pt ? "" : "/" + pt; 81 | #else 82 | ForgeTypeId pt = parameter.Definition.GetDataType(); 83 | string s = "/" + pt.TypeId.ToString(); 84 | #endif 85 | return parameter.StorageType + s; 86 | } 87 | 88 | /// 89 | /// Check Parameter Is Read Or Write 90 | /// 91 | /// 92 | /// 93 | public static string IsReadWrite(this Parameter parameter) 94 | { 95 | return parameter.IsReadOnly ? "Read Only" : "Read Write"; 96 | } 97 | 98 | 99 | /// 100 | /// Return value Of parameter all case unit 101 | /// 102 | /// 103 | /// 104 | public static string GetValue(this Autodesk.Revit.DB.Parameter _parameter) 105 | { 106 | string value; 107 | 108 | switch (_parameter.StorageType) 109 | { 110 | // database value, internal units, e.g. feet: 111 | case StorageType.Double: 112 | value = RealString(_parameter.AsDouble()); 113 | break; 114 | case StorageType.Integer: 115 | value = _parameter.AsInteger().ToString(); 116 | break; 117 | case StorageType.String: 118 | value = _parameter.AsString(); 119 | break; 120 | case StorageType.ElementId: 121 | value = _parameter.AsElementId().IntegerValue.ToString(); 122 | break; 123 | case StorageType.None: 124 | value = "None"; 125 | break; 126 | default: 127 | Debug.Assert(false, "unexpected storage type"); value = string.Empty; 128 | break; 129 | } 130 | 131 | return value; 132 | } 133 | 134 | /// 135 | /// Helper to return parameter value as string, with additional 136 | /// support for element id to display the element type referred to. 137 | /// 138 | public static string GetParameterValue2(this Parameter param, Document doc) 139 | { 140 | if (param.StorageType == StorageType.ElementId && doc != null) 141 | { 142 | var paramId = param.AsElementId(); 143 | var id = paramId.IntegerValue; 144 | 145 | if (id < 0) 146 | { 147 | return id.ToString() + BuiltInCategoryString(id); 148 | } 149 | else 150 | { 151 | var element = doc.GetElement(paramId); 152 | 153 | return ElementDescription(element, true); 154 | } 155 | } 156 | else 157 | { 158 | return GetParameterValue(param); 159 | } 160 | } 161 | 162 | static int _min_bic = 0; 163 | static int _max_bic = 0; 164 | static string BuiltInCategoryString(int id) 165 | { 166 | if (_min_bic == 0) 167 | { 168 | SetMinAndMaxBuiltInCategory(); 169 | } 170 | 171 | return (_min_bic < id && id < _max_bic) ? " " + ((BuiltInCategory)id).ToString() : string.Empty; 172 | } 173 | static void SetMinAndMaxBuiltInCategory() 174 | { 175 | var values = Enum.GetValues(typeof(BuiltInCategory)); 176 | _max_bic = values.Cast().Max(); 177 | _min_bic = values.Cast().Min(); 178 | } 179 | /// 180 | /// Return a description string including element id for a given element. 181 | /// 182 | public static string ElementDescription(Element element, bool includeId) 183 | { 184 | var description = ElementDescription(element); 185 | 186 | if (includeId) 187 | { 188 | description += " " + element.Id.IntegerValue.ToString(); 189 | } 190 | 191 | return description; 192 | } 193 | /// 194 | /// Return a description string for a given element. 195 | /// 196 | public static string ElementDescription(Element e) 197 | { 198 | var description = (null == e.Category) ? e.GetType().Name : e.Category.Name; 199 | 200 | if (e is FamilyInstance familyInstance) 201 | { 202 | description += " '" + familyInstance.Symbol.Family.Name + "'"; 203 | } 204 | 205 | if (null != e.Name) 206 | { 207 | description += " '" + e.Name + "'"; 208 | } 209 | 210 | return description; 211 | } 212 | 213 | /// 214 | /// Helper to return parameter value as string. 215 | /// One can also use param.AsValueString() to 216 | /// get the user interface representation. 217 | /// 218 | public static string GetParameterValue(Parameter param) 219 | { 220 | string parameterString; 221 | 222 | switch (param.StorageType) 223 | { 224 | case StorageType.Double: 225 | // 226 | // the internal database unit for all lengths is feet. 227 | // for instance, if a given room perimeter is returned as 228 | // 102.36 as a double and the display unit is millimeters, 229 | // then the length will be displayed as 230 | // peri = 102.36220472440 231 | // peri * 12 * 25.4 232 | // 31200 mm 233 | // 234 | //s = param.AsValueString(); // value seen by user, in display units 235 | //s = param.AsDouble().ToString(); // if not using not using LabUtils.RealString() 236 | parameterString = RealString(param.AsDouble()); // raw database value in internal units, e.g. feet 237 | break; 238 | 239 | case StorageType.Integer: 240 | parameterString = param.AsInteger().ToString(); 241 | break; 242 | 243 | case StorageType.String: 244 | parameterString = param.AsString(); 245 | break; 246 | 247 | case StorageType.ElementId: 248 | parameterString = param.AsElementId().IntegerValue.ToString(); 249 | break; 250 | 251 | case StorageType.None: 252 | parameterString = "?NONE?"; 253 | break; 254 | 255 | default: 256 | parameterString = "?ELSE?"; 257 | break; 258 | } 259 | 260 | return parameterString; 261 | } 262 | 263 | /// 264 | /// Return Result of parameter share 265 | /// 266 | /// parameter 267 | /// 268 | public static string Shared(this Parameter parameter) 269 | { 270 | return parameter.IsShared ? "Shared" : "Non-shared"; 271 | } 272 | 273 | /// 274 | /// Return Guid Of Parameter Share 275 | /// 276 | /// parameter 277 | /// 278 | public static string Guid(this Parameter parameter) 279 | { 280 | return parameter.IsShared ? parameter.GUID.ToString() : string.Empty; 281 | } 282 | 283 | 284 | /// 285 | /// Return Global Parameter Name 286 | /// 287 | /// 288 | /// 289 | /// 290 | public static string GetAssGlobalParameter(this Parameter parameter, Document doc) 291 | { 292 | Dictionary gloDictionary = new Dictionary(); 293 | ElementId elementId = parameter.GetAssociatedGlobalParameter(); 294 | if (elementId != null) 295 | { 296 | if (doc.GetElement(elementId) is GlobalParameter globalParameter) 297 | { 298 | return globalParameter.GetDefinition().Name; 299 | } 300 | } 301 | return string.Empty; 302 | } 303 | 304 | /// 305 | /// Return Global Parameter Value 306 | /// 307 | /// 308 | /// 309 | /// 310 | public static string GetAssGlobalParameterValue(this Parameter parameter, Document doc) 311 | { 312 | Dictionary gloDictionary = new Dictionary(); 313 | ElementId elementId = parameter.GetAssociatedGlobalParameter(); 314 | if (elementId != null) 315 | { 316 | if (doc.GetElement(elementId) is GlobalParameter globalParameter) 317 | { 318 | DoubleParameterValue doublevalue = globalParameter.GetValue() as DoubleParameterValue; 319 | StringParameterValue strpra = globalParameter.GetValue() as StringParameterValue; 320 | if (doublevalue != null) 321 | { 322 | return RealString(doublevalue.Value); 323 | } 324 | if (strpra != null) 325 | { 326 | return strpra.Value; 327 | } 328 | return string.Empty; 329 | 330 | } 331 | } 332 | return string.Empty; 333 | } 334 | 335 | } 336 | } 337 | -------------------------------------------------------------------------------- /Model/RelayCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Input; 4 | 5 | namespace RevitElementBipChecker.Model 6 | { 7 | /// 8 | /// A general relay command that takes its parameter as an object 9 | /// 10 | public class RelayCommand : ICommand 11 | { 12 | #region Variables 13 | private readonly Predicate m_canExecute; 14 | private readonly Action m_execute; 15 | private readonly Action _act; 16 | 17 | #endregion 18 | 19 | #region Constructor 20 | public RelayCommand(Action act) 21 | { 22 | _act = act; 23 | } 24 | 25 | public RelayCommand(Action execute, Predicate canExecute = null) 26 | { 27 | if (execute == null) 28 | { 29 | throw new ArgumentNullException("Execute"); 30 | } 31 | m_execute = execute; 32 | m_canExecute = canExecute; 33 | } 34 | #endregion 35 | 36 | #region Implementation 37 | // Evaluate the command if it is valid to execute 38 | public bool CanExecute(object parameter = null) 39 | { 40 | if (parameter == null || m_canExecute == null) return true; 41 | else return m_canExecute(parameter); 42 | } 43 | // Main execute method 44 | public void Execute(object parameter = null) 45 | { 46 | if (_act != null) _act(); 47 | else m_execute(parameter); 48 | } 49 | 50 | // In WPF CommandManager is a pre-defined class that take charge of observing the user interface 51 | // and calls the CanExecute method when it deems it necessary 52 | public event EventHandler CanExecuteChanged 53 | { 54 | add => CommandManager.RequerySuggested += value; 55 | remove => CommandManager.RequerySuggested -= value; 56 | } 57 | #endregion 58 | 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Model/RevitEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows; 4 | using Autodesk.Revit.DB; 5 | using Autodesk.Revit.UI; 6 | 7 | namespace OOG.Core.RevitData 8 | { 9 | public class RevitEvent : IExternalEventHandler 10 | { 11 | private Action _doAction; 12 | private Document _doc; 13 | private readonly ExternalEvent _exEvent; 14 | private bool _skipFailures; 15 | private string _transactionName; 16 | private bool withTransaction; 17 | public RevitEvent() 18 | { 19 | _exEvent = ExternalEvent.Create(this); 20 | } 21 | public void Run(Action doAction, bool skipFailures, Document doc = null, string transactionName = null, bool withTrans = true) 22 | { 23 | _doAction = doAction; 24 | _skipFailures = skipFailures; 25 | _doc = doc; 26 | withTransaction = withTrans; 27 | _exEvent.Raise(); 28 | _transactionName = transactionName; 29 | } 30 | public void Execute(UIApplication app) 31 | { 32 | try 33 | { 34 | if (_doAction != null) 35 | { 36 | if (_doc == null) _doc = app.ActiveUIDocument.Document; 37 | if (_skipFailures) 38 | app.Application.FailuresProcessing += Application_FailuresProcessing; 39 | 40 | if (withTransaction) 41 | { 42 | using (Transaction t = new Transaction(_doc, _transactionName ?? "RevitEvent")) 43 | { 44 | t.Start(); 45 | _doAction(); 46 | t.Commit(); 47 | } 48 | } 49 | else 50 | { 51 | _doAction(); 52 | } 53 | 54 | if (_skipFailures) 55 | app.Application.FailuresProcessing -= Application_FailuresProcessing; 56 | } 57 | } 58 | catch (Exception exception) 59 | { 60 | MessageBox.Show(exception.Message + Environment.NewLine + exception.StackTrace); 61 | if (_skipFailures) 62 | app.Application.FailuresProcessing -= Application_FailuresProcessing; 63 | } 64 | } 65 | 66 | private static void Application_FailuresProcessing(object sender, Autodesk.Revit.DB.Events.FailuresProcessingEventArgs e) 67 | { 68 | // Inside event handler, get all warnings 69 | var failList = e.GetFailuresAccessor().GetFailureMessages(); 70 | if (failList.Any()) 71 | { 72 | // skip all failures 73 | e.GetFailuresAccessor().DeleteAllWarnings(); 74 | e.SetProcessingResult(FailureProcessingResult.Continue); 75 | } 76 | } 77 | 78 | public string GetName() 79 | { 80 | return "RevitEvent"; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Model/StringUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | 9 | namespace RevitElementBipChecker.Model 10 | { 11 | public static class StringUtils 12 | { 13 | public static string RemoveInvalid(this string str) 14 | { 15 | string rExp = @"[^\w\d]"; 16 | string replace = Regex.Replace(str, rExp, ""); 17 | string trim = replace.Trim(); 18 | return trim.TrimWhitespace().FirstOrDefault(); 19 | } 20 | 21 | private static Regex Whitespaces = new Regex(@"\s+"); 22 | public static string[] TrimWhitespace(this string input) 23 | { 24 | return Whitespaces.Split(input.Trim()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Model/WindowHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using System.Windows; 5 | using System.Windows.Interop; 6 | 7 | namespace RevitElementBipChecker.Model 8 | { 9 | public static class WindowHandle 10 | { 11 | [DllImport("kernel32.dll")] 12 | public static extern uint GetCurrentThreadId(); 13 | 14 | /// 15 | /// Sets the given window's owner to Revit window. 16 | /// 17 | /// Target window. 18 | public static void SetRevitAsWindowOwner(this Window dialog) 19 | { 20 | if (null == dialog) { return; } 21 | 22 | WindowInteropHelper helper = new WindowInteropHelper(dialog); 23 | helper.Owner = FindRevitWindowHandle(); 24 | } 25 | 26 | /// 27 | /// Finds the Revit window handle. 28 | /// 29 | /// Revit window handle. 30 | private static IntPtr FindRevitWindowHandle() 31 | { 32 | try 33 | { 34 | IntPtr foundRevitHandle = IntPtr.Zero; 35 | uint currentThreadID = GetCurrentThreadId(); 36 | 37 | // Search for the Revit process with current thread ID. 38 | Process[] revitProcesses = Process.GetProcessesByName("Revit"); 39 | Process foundRevitProcess = null; 40 | foreach (Process aRevitProcess in revitProcesses) 41 | { 42 | foreach (ProcessThread aThread in aRevitProcess.Threads) 43 | { 44 | if (aThread.Id == currentThreadID) 45 | { 46 | foundRevitProcess = aRevitProcess; 47 | break; 48 | } 49 | } // For each thread in the process. 50 | 51 | // When we have found our Revit process, then stop searching. 52 | if (null != foundRevitProcess) { break; } 53 | } // For each revit process found 54 | 55 | // Get the window handle of the Revit process found. 56 | if (null != foundRevitProcess) 57 | { 58 | foundRevitHandle = foundRevitProcess.MainWindowHandle; 59 | } 60 | 61 | return foundRevitHandle; 62 | } 63 | catch (Exception) 64 | { 65 | return IntPtr.Zero; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RevitElementBipChecker")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("https://chuongmep.com/")] 12 | [assembly: AssemblyProduct("RevitElementBipChecker")] 13 | [assembly: AssemblyCopyright("Copyright ©Chuongmep 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("325F1D8A-E9A2-4CA4-93C3-D977B3DDD81B")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RevitElementBipChecker 2 | ![Revit API](https://img.shields.io/badge/Revit%20API-2021-blue.svg) 3 | ![Platform](https://img.shields.io/badge/platform-Windows-lightgray.svg) 4 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 5 | 6 | follow on Twitter 8 | 9 | Project Update From ottosson and jeremytammik with WPF Solution And Extend Funtion, fix Error for package nuget dependent old with .NET. 10 | 11 | ### Download 12 | 13 | RevitElementBipChecker 14 | 15 | ### Solution Check Full Parameter : 16 | 17 | - Search Parameter Of Element And Snoop All Value For Developer 18 | - Support Parameter Type And Instance 19 | - Export Parameter to Excel (*csv format*) 20 | - Export Parameter to Json (*json format*) 21 | - Interactive Live With Revit Project 22 | - Select Quickly Change Snoop Element 23 | - Support Snoop LinkedElement 24 | - Support Copy Parameter Infomation 25 | 26 | ### Select First To Snoop : 27 | 28 | ![](doc/_Image_7f2dfd6b-9f5c-4732-9cb8-fb1e05c7c205.png) 29 | 30 | ### Main Form : 31 | 32 | ![](doc/Revit_dGgL1g5tq4.png) 33 | 34 | ### Live Snoop 35 | 36 | ![](doc/GIWlYwW8wt.gif) 37 | 38 | ### Data Export Excel 39 | 40 | ![](doc/_Image_f1aac13a-394a-4b91-87d3-02ecf8bfd3ef.png) 41 | 42 | ### Data Export Json 43 | 44 | ![](doc/_Image_8818052f-5f71-46f9-8d4c-314997031280.png) 45 | 46 | 47 | ### Copy Info By Right Click 48 | 49 | ![](doc/Revit_HmBMFy23mM.png) 50 | 51 | ### How To Use 52 | 53 | #### Clone project from : 54 | 55 | ``` 56 | git clone https://github.com/chuongmep/RevitElementBipChecker.git 57 | ``` 58 | #### Restore nuget : 59 | 60 | 61 | 2.[https://github.com/JamesNK/Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) 62 | 63 | #### Build solution: 64 | 65 | 1. _RevitElementBipChecker.dll_ 66 | 2. _BipChecker.addin_ 67 | 68 | ### Reference 69 | 70 | jeremytammik 71 | 72 | ottosson 73 | -------------------------------------------------------------------------------- /RevitElementBipChecker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net48 4 | Library 5 | x64 6 | false 7 | true 8 | true 9 | Debug R22 10 | $(Configurations);R18;R19;R20;R21;R22;R23 11 | 12 | 13 | true 14 | full 15 | $(DefineConstants);DEBUG 16 | 17 | 18 | true 19 | none 20 | $(DefineConstants);RELEASE 21 | 22 | 23 | bin\REVIT2023\ 24 | R23 25 | 2023 26 | 27 | 28 | bin\REVIT2022\ 29 | R22 30 | 2022 31 | 32 | 33 | bin\REVIT2021\ 34 | R21 35 | 2021 36 | 37 | 38 | bin\REVIT2020\ 39 | R20 40 | 2020 41 | 42 | 43 | bin\REVIT2019\ 44 | R19 45 | 2019 46 | 47 | 48 | bin\REVIT2018\ 49 | R18 50 | 2018 51 | 52 | 53 | 54 | $(RevitVersion) 55 | false 56 | A Project Support Parameter Database for developer in revit 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /RevitElementBipChecker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.31911.260 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RevitElementBipChecker", "RevitElementBipChecker.csproj", "{BA7F5127-5343-4EF3-8A81-0497391AEE46}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug R23|Any CPU = Debug R23|Any CPU 11 | R18|Any CPU = R18|Any CPU 12 | R19|Any CPU = R19|Any CPU 13 | R20|Any CPU = R20|Any CPU 14 | R21|Any CPU = R21|Any CPU 15 | R22|Any CPU = R22|Any CPU 16 | R23|Any CPU = R23|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.Debug R23|Any CPU.ActiveCfg = Debug R22|Any CPU 20 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.Debug R23|Any CPU.Build.0 = Debug R22|Any CPU 21 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R18|Any CPU.ActiveCfg = R18|Any CPU 22 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R18|Any CPU.Build.0 = R18|Any CPU 23 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R19|Any CPU.ActiveCfg = R19|Any CPU 24 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R19|Any CPU.Build.0 = R19|Any CPU 25 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R20|Any CPU.ActiveCfg = R20|Any CPU 26 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R20|Any CPU.Build.0 = R20|Any CPU 27 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R21|Any CPU.ActiveCfg = R21|Any CPU 28 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R21|Any CPU.Build.0 = R21|Any CPU 29 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R22|Any CPU.ActiveCfg = R22|Any CPU 30 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R22|Any CPU.Build.0 = R22|Any CPU 31 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R23|Any CPU.ActiveCfg = R23|Any CPU 32 | {BA7F5127-5343-4EF3-8A81-0497391AEE46}.R23|Any CPU.Build.0 = R23|Any CPU 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(ExtensibilityGlobals) = postSolution 38 | SolutionGuid = {CCB0C1D3-4D9F-420B-9F51-404B2ACA81C4} 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /View/MainWindows.xaml: -------------------------------------------------------------------------------- 1 |  17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |