Wednesday, June 11, 2008

Microsoft Project FX (mpFx) - New mpFx Library & Wrapper for Graphical Indicators

I am poised to get ripped from my current project (building an internal system around Microsoft Project)  temporarily to work on a product-related problem.

But before I disappear for a couple of days, I wanted to let the mpFx team know where I am at with the experimental build.  I have included a new library in the mix that provides a series of WinForms dialogs for doing miscellaneous things with custom fields.  This is old code that I moved over to mpFx and modified to fit into the framework.  The new library is CodePlex.MicrosoftProject.mpFx.WinForms and will house all reusable WinForms dialogs, forms, and controls.  Here are some screen shots...

Custom Field Editor

image

Custom Field Editor - Set Lookup Table Options

image

Select Lookup Table Value

image

Graphical Indicators Editor

image 

Figuring out the graphical indicators was fun.  Here is a the wrapper class:

   1: /* ------------------------------------------------------------------------------------------------------- 
   2:  * Microsoft Project Fx (mpFx) - Tools & Technologies for Building Solutions with Microsoft Office Project 
   3:  * -------------------------------------------------------------------------------------------------------
   4:  * File:    CodePlex.MicrosoftProject.mpFx.GraphicalIndicator.cs
   5:  * Author:  Colby Africa
   6:  * Genesis: 2008-06-11
   7:  * License: Microsoft Public License 
   8:  *          (http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx)
   9:  * -------------------------------------------------------------------------------------------------------
  10:  * See footer for change log
  11:  * -------------------------------------------------------------------------------------------------------
  12:  */
  13:  
  14: using System;
  15: using System.Collections;
  16: using System.Collections.Generic;
  17: using System.Diagnostics;
  18: using System.Text;
  19: using System.Text.RegularExpressions;
  20: using Microsoft.Office.Project.Server.Library;
  21:  
  22: namespace CodePlex.MicrosoftProject.mpFx
  23: {
  24:     /// <summary>
  25:     /// Wraps Project's Graphical Indicator criteria string
  26:     /// </summary>
  27:     public class GraphicalIndicator
  28:     {
  29:         #region Constants
  30:  
  31:         public static readonly int MAX_NUMBER_OF_CRITERIA = 3;
  32:         public static readonly int MAX_IMAGE_INDEX = 65;
  33:  
  34:         #endregion
  35:  
  36:         #region Instance Data
  37:  
  38:         private static readonly Dictionary<string, string> _Tests = new Dictionary<string, string>();
  39:         private readonly Dictionary<int, Criteria> _ProjectSummaryCriteria = new Dictionary<int, Criteria>();
  40:         private readonly Dictionary<int, Criteria> _SummaryCriteria = new Dictionary<int, Criteria>();
  41:         private readonly Dictionary<int, Criteria> _NonSummaryCriteria = new Dictionary<int, Criteria>();
  42:  
  43:         #endregion
  44:  
  45:         #region Enums
  46:  
  47:         public enum CriteriaFor
  48:         {
  49:             None,
  50:             NonSummaryRows,
  51:             ProjectSummary,
  52:             Summary
  53:         }
  54:  
  55:         #endregion
  56:  
  57:         #region Constructor
  58:  
  59:         /// <summary>
  60:         /// Create an instance of GraphicalIndicator
  61:         /// </summary>
  62:         /// <param name="entityGuid">The GUID of the entity (Project, Task, Resource)</param>
  63:         /// <param name="customField">The CustomField definition of the field for which the Graphical Indicator will be associated with</param>
  64:         /// <param name="customFieldType">The custom field type (Cost, Date, Duration, Flag, Number, and Text</param>
  65:         public GraphicalIndicator(Guid entityGuid,
  66:                                   CustomFieldDefinition customField,
  67:                                   CustomField.Type customFieldType)
  68:         {
  69:             if (customField == null)
  70:             {
  71:                 throw new ArgumentNullException("customField");
  72:             }
  73:  
  74:             if (entityGuid == Guid.Empty || !IsValidEntityForGraphicalIndicator(entityGuid))
  75:             {
  76:                 throw new ArgumentException("Invalid entity Guid");
  77:             }
  78:  
  79:             if (customFieldType == CustomField.Type.FINISHDATE)
  80:             {
  81:                 throw new ArgumentException("Invalid custom field type");
  82:             }
  83:  
  84:             EntityGuid = entityGuid;
  85:             CustomFieldDefinition = customField;
  86:             CustomFieldType = customFieldType;
  87:  
  88:             LoadTests();
  89:  
  90:             UnpackCustomField();
  91:         }
  92:  
  93:         #endregion
  94:  
  95:         #region Public Methods
  96:  
  97:         /// <summary>
  98:         /// Add criteria to a specific type (Non Summary Rows,Project Summary,and Summary)
  99:         /// </summary>
 100:         /// <param name="criteriaFor">Designates which criteria collection the criteria will be added to</param>
 101:         /// <param name="criteria">The criteria to add</param>
 102:         public void AddCriteria(CriteriaFor criteriaFor,
 103:                                 Criteria criteria)
 104:         {
 105:             if (criteria.ImageIndex == 0)
 106:             {
 107:                 throw new ArgumentException("criteria");
 108:             }
 109:  
 110:             if (string.IsNullOrEmpty(criteria.Test))
 111:             {
 112:                 throw new ArgumentException("criteria");
 113:             }
 114:  
 115:             if (string.IsNullOrEmpty(criteria.Value))
 116:             {
 117:                 throw new ArgumentException("criteria");
 118:             }
 119:  
 120:             Dictionary<int, Criteria> thisCollection;
 121:  
 122:             switch (criteriaFor)
 123:             {
 124:                 case CriteriaFor.None:
 125:                     throw new ArgumentException("criteria");
 126:  
 127:                 case CriteriaFor.NonSummaryRows:
 128:                     thisCollection = _NonSummaryCriteria;
 129:                     break;
 130:  
 131:                 case CriteriaFor.ProjectSummary:
 132:                     thisCollection = _ProjectSummaryCriteria;
 133:                     break;
 134:  
 135:                 case CriteriaFor.Summary:
 136:                     thisCollection = _SummaryCriteria;
 137:                     break;
 138:  
 139:                 default:
 140:                     throw new ArgumentOutOfRangeException("criteriaFor");
 141:             }
 142:  
 143:             Debug.Assert(thisCollection != null);
 144:  
 145:             if (thisCollection.Count + 1 > MAX_NUMBER_OF_CRITERIA)
 146:             {
 147:                 throw new IndexOutOfRangeException();
 148:             }
 149:  
 150:             thisCollection.Add(criteria.Index, criteria);
 151:         }
 152:  
 153:         /// <summary>
 154:         /// Retrieve the criteria for the given type at the given index
 155:         /// </summary>
 156:         /// <param name="criteriaFor">Designates which criteria collection to retrieve from</param>
 157:         /// <param name="index">The index of the criteria</param>
 158:         /// <returns>The requested criteria</returns>
 159:         public Criteria GetCriteria(CriteriaFor criteriaFor,
 160:                                     int index)
 161:         {
 162:             switch (criteriaFor)
 163:             {
 164:                 case CriteriaFor.NonSummaryRows:
 165:                     return _NonSummaryCriteria[index];
 166:                 case CriteriaFor.ProjectSummary:
 167:                     return _ProjectSummaryCriteria[index];
 168:                 case CriteriaFor.Summary:
 169:                     return _SummaryCriteria[index];
 170:                 default:
 171:                     throw new ArgumentOutOfRangeException("criteriaFor");
 172:             }
 173:         }
 174:  
 175:         /// <summary>
 176:         /// Returns the criteria string for the specified criteria type
 177:         /// </summary>
 178:         /// <param name="criteriaFor">Designates which criteria should be render as the return string</param>
 179:         /// <returns>The criteria string</returns>
 180:         public string GetCriteriaString(CriteriaFor criteriaFor)
 181:         {
 182:             Dictionary<int, Criteria> thisCollection;
 183:  
 184:             switch (criteriaFor)
 185:             {
 186:                 case CriteriaFor.NonSummaryRows:
 187:                     thisCollection = _NonSummaryCriteria;
 188:                     break;
 189:                 case CriteriaFor.ProjectSummary:
 190:                     thisCollection = _ProjectSummaryCriteria;
 191:                     break;
 192:                 case CriteriaFor.Summary:
 193:                     thisCollection = _SummaryCriteria;
 194:                     break;
 195:                 default:
 196:                     throw new ArgumentOutOfRangeException("criteriaFor");
 197:             }
 198:  
 199:             StringBuilder criteriaString = new StringBuilder();
 200:  
 201:             foreach (KeyValuePair<int, Criteria> pair in thisCollection)
 202:             {
 203:                 criteriaString.AppendFormat("[[{0}\t{1}\t\t][{2}]]", 
 204:                                             _Tests[pair.Value.Test], 
 205:                                             pair.Value.Value, 
 206:                                             pair.Value.ImageIndex);
 207:             }
 208:  
 209:             return criteriaString.ToString();
 210:         }
 211:  
 212:         /// <summary>
 213:         /// Given a specific criteria type, return the count of criteria
 214:         /// </summary>
 215:         /// <param name="criteriaFor">The criteria type</param>
 216:         /// <returns>The count</returns>
 217:         public int GetCount(CriteriaFor criteriaFor)
 218:         {
 219:             switch (criteriaFor)
 220:             {
 221:                 case CriteriaFor.NonSummaryRows:
 222:                     return _NonSummaryCriteria.Count;
 223:                 case CriteriaFor.ProjectSummary:
 224:                     return _ProjectSummaryCriteria.Count;
 225:                 case CriteriaFor.Summary:
 226:                     return _SummaryCriteria.Count;
 227:                 default:
 228:                     throw new ArgumentOutOfRangeException("criteriaFor");
 229:             }
 230:         }
 231:  
 232:         /// <summary>
 233:         /// Given a specific criteria type, clear its criteria
 234:         /// </summary>
 235:         /// <param name="criteriaFor">The criteria type to clear</param>
 236:         public void ClearCriteria(CriteriaFor criteriaFor)
 237:         {
 238:             switch (criteriaFor)
 239:             {
 240:                 case CriteriaFor.None:
 241:                     break;
 242:                 case CriteriaFor.NonSummaryRows:
 243:                     _NonSummaryCriteria.Clear();
 244:                     break;
 245:                 case CriteriaFor.ProjectSummary:
 246:                     _ProjectSummaryCriteria.Clear();
 247:                     break;
 248:                 case CriteriaFor.Summary:
 249:                     _SummaryCriteria.Clear();
 250:                     break;
 251:                 default:
 252:                     throw new ArgumentOutOfRangeException("criteriaFor");
 253:             }
 254:         }
 255:  
 256:         /// <summary>
 257:         /// Parses the criteria string
 258:         /// </summary>
 259:         /// <param name="criteriaString"></param>
 260:         /// <returns>A stack representing the individual criteria componentes </returns>
 261:         public Stack ParseCriteriaString(string criteriaString)
 262:         {
 263:             /*  The criteria string format is as follows 
 264:              *  Brackets arrange to appear like code for readability.
 265:              *  See sample below for what the string looks like):              
 266:              *  [    
 267:              *      [
 268:              *          <test> \t <value> \t\t
 269:              *      ]
 270:              *      [
 271:              *          <image index>
 272:              *      ]
 273:              *  ]
 274:              *  [
 275:              *      [
 276:              *          <test> \t <value> \t\t 
 277:              *      ]
 278:              *      [
 279:              *          <image index>
 280:              *      ]
 281:              *  ]
 282:              *  ... Up to three criteria
 283:              *  
 284:              *  Here is a sample:
 285:              *  
 286:              *  [[DoesntContain\ttest\t\t][63]][[==\t10\t\t][1]][[==\t12\t\t][3]]
 287:              *  
 288:              */
 289:             Regex tokenizer = new Regex(@"\[(?<Tokens>([^\]])*)\]");
 290:             MatchCollection tokens = tokenizer.Matches(criteriaString);
 291:             Stack criteria = new Stack();
 292:  
 293:             for (int matchCount = 0; matchCount < tokens.Count; matchCount++)
 294:             {
 295:                 string token = tokens[matchCount].Value;
 296:  
 297:                 token = token.Replace("[", "");
 298:                 token = token.Replace("]", "");
 299:  
 300:                 token = token.Trim();
 301:  
 302:                 string[] components = token.Split('\t');
 303:  
 304:                 for (int i = 0; i < components.Length; i++)
 305:                 {
 306:                     criteria.Push(components[i]);
 307:                 }
 308:             }
 309:  
 310:             return criteria;
 311:         }
 312:  
 313:         /// <summary>
 314:         /// Given a specific test string (for example '==' or '!='), 
 315:         /// return its display name (equals or does not equal)
 316:         /// </summary>
 317:         /// <param name="testString">The test string to look up</param>
 318:         /// <returns>The display name of the test string</returns>
 319:         public static string GetDisplayName(string testString)
 320:         {
 321:             foreach (KeyValuePair<string, string> test in _Tests)
 322:             {
 323:                 if (test.Value.Equals(testString, 
 324:                                       StringComparison.CurrentCultureIgnoreCase)) {
 325:                     return test.Key;
 326:                 }
 327:             }
 328:  
 329:             return null;
 330:         }
 331:  
 332:         #endregion
 333:  
 334:         #region Public Properties
 335:  
 336:         /// <summary>
 337:         /// Retrieve an error of the tests' display names
 338:         /// </summary>
 339:         public string[] TestsDisplayNames
 340:         {
 341:             get
 342:             {
 343:                 string[] testDisplayNames = new string[_Tests.Keys.Count];
 344:  
 345:                 _Tests.Keys.CopyTo(testDisplayNames, 0);
 346:  
 347:                 return testDisplayNames;
 348:             }
 349:         }
 350:  
 351:         /// <summary>
 352:         /// Retrieve and privately set the Graphical Indicator's underlying entity GUID
 353:         /// </summary>
 354:         public Guid EntityGuid { get; private set; }
 355:  
 356:         /// <summary>
 357:         /// Retrieve and privately set the CustomField type
 358:         /// </summary>
 359:         public CustomField.Type CustomFieldType { get; private set; }
 360:  
 361:         /// <summary>
 362:         /// Retrieve the count of Project Summary criteria
 363:         /// </summary>
 364:         public int ProjectSummaryCriteriaCount
 365:         {
 366:             get { return _ProjectSummaryCriteria.Count; }
 367:         }
 368:  
 369:         /// <summary>
 370:         /// Retrieve the count of Summary criteria
 371:         /// </summary>
 372:         public int SummaryCriteriaCount
 373:         {
 374:             get { return _SummaryCriteria.Count; }
 375:         }
 376:  
 377:         /// <summary>
 378:         /// Retrieve the count of Non Summary criteria
 379:         /// </summary>
 380:         public int NonSummaryCriteriaCount
 381:         {
 382:             get { return _NonSummaryCriteria.Count; }
 383:         }
 384:  
 385:         #endregion
 386:  
 387:         #region Private Methods
 388:  
 389:         /// <summary>
 390:         /// Unpack the criteria in the custom field definition, which is in Project Server format
 391:         /// into Criteria collections
 392:         /// </summary>
 393:         private void UnpackCustomField()
 394:         {
 395:             if (!string.IsNullOrEmpty(CustomFieldDefinition.NonSummaryCriteriaString))
 396:             {
 397:                 Stack components = ParseCriteriaString(CustomFieldDefinition.NonSummaryCriteriaString);
 398:  
 399:                 AddCriteria(CriteriaFor.NonSummaryRows, components);
 400:             }
 401:  
 402:             if (!string.IsNullOrEmpty(CustomFieldDefinition.ProjectSummaryCriteriaString))
 403:             {
 404:                 Stack components = ParseCriteriaString(CustomFieldDefinition.ProjectSummaryCriteriaString);
 405:  
 406:                 AddCriteria(CriteriaFor.ProjectSummary, components);
 407:             }
 408:  
 409:             if (!string.IsNullOrEmpty(CustomFieldDefinition.SummaryTaskCriteriaString))
 410:             {
 411:                 Stack components = ParseCriteriaString(CustomFieldDefinition.SummaryTaskCriteriaString);
 412:  
 413:                 AddCriteria(CriteriaFor.Summary, components);
 414:             }
 415:         }
 416:  
 417:         /// <summary>
 418:         /// Adds criteria from a stack of criteria components (returned by ParseCriteriaString
 419:         /// </summary>
 420:         /// <param name="criteriaFor">The critieria types</param>
 421:         /// <param name="criteriaComponents">The stack of criteria componentes</param>
 422:         private void AddCriteria(CriteriaFor criteriaFor,
 423:                                  Stack criteriaComponents)
 424:         {
 425:             int operationsCount = criteriaComponents.Count;
 426:  
 427:             // Three components per criteria: image index, value, and test 
 428:             for (int counter = 0; counter < operationsCount/3; counter++)
 429:             {
 430:                 Criteria criteria = new Criteria(Convert.ToInt32(criteriaComponents.Pop()),
 431:                                                  criteriaComponents.Pop().ToString(), 
 432:                                                  GetDisplayName(criteriaComponents.Pop().ToString()), counter);
 433:  
 434:                 AddCriteria(criteriaFor, criteria);
 435:             }
 436:         }
 437:  
 438:         // Load the static list of tests and each test's corresponding Project Server token
 439:         private static void LoadTests()
 440:         {
 441:             if (_Tests.Count == 0)
 442:             {
 443:                 _Tests.Add("equals", "==");
 444:                 _Tests.Add("does not equal", "!=");
 445:                 _Tests.Add("is greater than", ">");
 446:                 _Tests.Add("is greater than or equal to", ">=");
 447:                 _Tests.Add("is less than", "<");
 448:                 _Tests.Add("is less than or equal to", "<=");
 449:                 _Tests.Add("is within", "Between");
 450:                 _Tests.Add("is not within", "NotBetween");
 451:                 _Tests.Add("contains", "Contains");
 452:                 _Tests.Add("doesn't contain", "DoesntContain");
 453:                 _Tests.Add("contains exactly", "ContainsExactly");
 454:                 _Tests.Add("any value", "ANY");
 455:             }
 456:         }
 457:  
 458:         /// <summary>
 459:         /// Given a entity guid, determine whether or not a graphical indicator can be associated with the 
 460:         /// custom field
 461:         /// </summary>
 462:         /// <param name="entity">The entity's GUID</param>
 463:         /// <returns>True if Project, Task, or Resource; false otherwise</returns>
 464:         private static bool IsValidEntityForGraphicalIndicator(Guid entity)
 465:         {
 466:             string entityString = entity.ToString().ToLower();
 467:  
 468:             return (entityString == Utilities.GetEntityGuidStringFromName("Project").ToLower() ||
 469:                     entityString == Utilities.GetEntityGuidStringFromName("Task").ToLower() ||
 470:                     entityString == Utilities.GetEntityGuidStringFromName("Resource").ToLower());
 471:         }
 472:  
 473:         #endregion
 474:  
 475:         #region Private Properties
 476:  
 477:         /// <summary>
 478:         /// Retrieve the Graphical Indicator's associated CustomFieldDefinition
 479:         /// </summary>
 480:         private CustomFieldDefinition CustomFieldDefinition { get; set; }
 481:  
 482:         #endregion
 483:  
 484:         #region Classes
 485:  
 486:         /// <summary>
 487:         /// A very simple wrapper around Project Server's graphical indicator
 488:         /// </summary>
 489:         public class Criteria
 490:         {
 491:             /// <summary>
 492:             /// Construct an instance of Criteria
 493:             /// </summary>
 494:             /// <param name="imageIndex">The image index</param>
 495:             /// <param name="value">The value to test</param>
 496:             /// <param name="test">The test</param>
 497:             /// <param name="index">The index (or ordinal) of the criteria</param>
 498:             public Criteria(int imageIndex,
 499:                             string value,
 500:                             string test,
 501:                             int index)
 502:             {
 503:                 Index = index;
 504:                 ImageIndex = imageIndex;
 505:                 Test = test;
 506:                 Value = value;
 507:             }
 508:  
 509:             /// <summary>
 510:             /// Auto properties for instance data
 511:             /// </summary>
 512:             public int Index { get; private set; }
 513:  
 514:             public int ImageIndex { get; private set; }
 515:             public string Value { get; private set; }
 516:             public string Test { get; private set; }
 517:         }
 518:  
 519:         #endregion
 520:     }
 521: }
 522:  
 523: /* ------------------------------------------------------------------------------------------------------- 
 524:  * Change Log
 525:  * -------------------------------------------------------------------------------------------------------
 526:  * 2008-06-11: Colby Africa - Added header and footer
 527:  * 2008-06-11: Colby Africa - Regionized members
 528: */

Here is a partially completed wrapper of a custom field definition: 

   1: /* ------------------------------------------------------------------------------------------------------- 
   2:  * Microsoft Project Fx (mpFx) - Tools & Technologies for Building Solutions with Microsoft Office Project 
   3:  * -------------------------------------------------------------------------------------------------------
   4:  * File:    CodePlex.MicrosoftProject.mpFx.CustomFieldDefinition.cs
   5:  * Author:  Colby Africa
   6:  * Genesis: 2008-06-01
   7:  * License: Microsoft Public License 
   8:  *          (http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx)
   9:  * -------------------------------------------------------------------------------------------------------
  10:  * See footer for change log
  11:  * -------------------------------------------------------------------------------------------------------
  12:  */
  13: using System;
  14: using CodePlex.MicrosoftProject.mpFx.CustomFieldsWebService;
  15: using Microsoft.Office.Project.Server.Library;
  16:  
  17: namespace CodePlex.MicrosoftProject.mpFx
  18: {
  19:     /// <summary>
  20:     /// Wrapper class for Microsoft Project Server custom fields
  21:     /// </summary>
  22:     public class CustomFieldDefinition
  23:     {
  24:         #region Public Enums
  25:  
  26:         public enum AttributeTypes
  27:         {
  28:             None,
  29:             LookupTable,
  30:             Formula
  31:         }
  32:  
  33:         public enum DisplayTypes
  34:         {
  35:             None,
  36:             Data,
  37:             GraphicalIndicators
  38:         }
  39:  
  40:         #endregion
  41:  
  42:         //  General fields
  43:         #region Constructors
  44:  
  45:         /// <summary>
  46:         /// Create an instance of CustomFieldDefinition with its name set
  47:         /// </summary>
  48:         /// <param name="name">The custom field's name</param>
  49:         public CustomFieldDefinition(string name)
  50:         {
  51:             Name = name;
  52:         }
  53:  
  54:         /// <summary>
  55:         /// Given a CustomFieldDataSet.CustomFieldsRow, create an instance of CustomFieldDefinition
  56:         /// </summary>
  57:         /// <param name="customField">CustomFieldDataSet.CustomFieldsRow object</param>
  58:         public CustomFieldDefinition(CustomFieldDataSet.CustomFieldsRow customField)
  59:         {
  60:             Type = (CustomField.Type) customField.MD_PROP_TYPE_ENUM;
  61:             EntityGuid = customField.MD_ENT_TYPE_UID;
  62:             Guid = customField.MD_PROP_UID;
  63:             Name = customField.MD_PROP_NAME;
  64:             IsRequired = customField.MD_PROP_IS_REQUIRED;
  65:             
  66:             if (!customField.IsMD_LOOKUP_TABLE_UIDNull())
  67:             {
  68:                 AttributeType = AttributeTypes.LookupTable;
  69:                 LookupTableGuid = customField.MD_LOOKUP_TABLE_UID;
  70:  
  71:                 if (!customField.IsMD_PROP_DEFAULT_VALUENull())
  72:                 {
  73:                     DefaultValueGuid = customField.MD_PROP_DEFAULT_VALUE;
  74:                 }
  75:  
  76:                 if (!customField.IsMD_PROP_IS_LEAF_NODE_ONLYNull())
  77:                 {
  78:                     LeafOnly = customField.MD_PROP_IS_LEAF_NODE_ONLY;
  79:                 }
  80:  
  81:                 if (!customField.IsMD_PROP_MAX_VALUESNull())
  82:                 {
  83:                     MultiSelect = (CustomField.AcceptableMaxValues) customField.MD_PROP_MAX_VALUES;
  84:                 }
  85:                 
  86:             } else if (!customField.IsMD_PROP_FORMULANull())
  87:             {
  88:                 AttributeType = AttributeTypes.Formula;
  89:                 Formula = customField.MD_PROP_FORMULA;
  90:             }
  91:             else
  92:             {
  93:                 MultiSelect = CustomField.AcceptableMaxValues.DEFAULT;
  94:                 AttributeType = AttributeTypes.None;
  95:             }
  96:  
  97:             if (!customField.IsMD_PROP_GRAPHICAL_INDICATORNull())
  98:             {
  99:                 DisplayType = DisplayTypes.GraphicalIndicators;
 100:  
 101:                 NonSummaryCriteriaString = customField.MD_PROP_GRAPHICAL_INDICATOR;
 102:             }
 103:             
 104:             if (!customField.IsMD_PROP_PROJ_SUMM_GRAPHICAL_INDICATORNull())
 105:             {
 106:                 DisplayType = DisplayTypes.GraphicalIndicators;
 107:  
 108:                 ProjectSummaryCriteriaString = customField.MD_PROP_PROJ_SUMM_GRAPHICAL_INDICATOR;                
 109:             }
 110:             
 111:             if (!customField.IsMD_PROP_SUMM_GRAPHICAL_INDICATORNull())
 112:             {
 113:                 DisplayType = DisplayTypes.GraphicalIndicators;
 114:  
 115:                 SummaryTaskCriteriaString = customField.MD_PROP_SUMM_GRAPHICAL_INDICATOR;                                
 116:             }
 117:             else
 118:             {
 119:                 DisplayType = DisplayTypes.Data;
 120:             }
 121:             
 122:             if (!customField.IsMD_PROP_GRAPHICAL_INDICATOR_TOOLTIPNull())
 123:             {
 124:                 ShowValuesInTooltip = customField.MD_PROP_GRAPHICAL_INDICATOR_TOOLTIP;
 125:             }
 126:         }
 127:  
 128:         #endregion
 129:  
 130:         #region Public Properties
 131:  
 132:         /// <summary>
 133:         /// Basic properties
 134:         /// </summary>
 135:         public CustomField.Type Type { get; set; }
 136:         public Guid EntityGuid { get; set; } // MSProject.EntityCollection
 137:         public Guid Guid { get; set; }
 138:         public string Name { get; set; }
 139:         public bool IsRequired { get; set; }
 140:         public AttributeTypes AttributeType { get; set; }
 141:         public DisplayTypes DisplayType { get; set; }
 142:  
 143:         //  Lookup table properties
 144:         public Guid LookupTableGuid { get; set; }
 145:         public Guid DefaultValueGuid { get; set; }
 146:         public bool LeafOnly { get; set; }
 147:         public CustomField.AcceptableMaxValues MultiSelect { get; set; }
 148:  
 149:         //  Formula properties
 150:         public string Formula { get; set; }
 151:  
 152:         //  Graphical Indicators properties
 153:         public string ProjectSummaryCriteriaString { get; set; }
 154:         public string SummaryTaskCriteriaString { get; set; }
 155:         public string NonSummaryCriteriaString { get; set; }
 156:         public bool ShowValuesInTooltip { get; set; }
 157:  
 158:         #endregion
 159:     }
 160: }
 161: /* ------------------------------------------------------------------------------------------------------- 
 162:  * Change Log
 163:  * -------------------------------------------------------------------------------------------------------
 164:  * 2008-06-06: Colby Africa - Added header and footer
 165:  * 2008-06-06: Colby Africa - Regionized members
 166: */

No comments :

Disclaimer

Content on this site is provided "AS IS" with no warranties and confers no rights. Additionally, all content on this site is my own personal opinion and does not represent my employer's view in any way.