// set new parameter collection; update collection change notification handler
 private void SetPathParameterCollection(PathParameterCollection parameters)
 {
     if (_parameters != null)
     {
         _parameters.CollectionChanged -= new NotifyCollectionChangedEventHandler(ParameterCollectionChanged);
     }
     _parameters = parameters;
     if (_parameters != null)
     {
         _parameters.CollectionChanged += new NotifyCollectionChangedEventHandler(ParameterCollectionChanged);
     }
 }
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        /// <summary>
        /// Construct a PropertyPath from a string and a list of parameters
        /// </summary>
        public PropertyPath(string path, params object[] pathParameters)
        {
            if (System.Windows.Threading.Dispatcher.CurrentDispatcher == null)
            {
                throw new InvalidOperationException();  // This is actually never called since CurrentDispatcher will throw if null.
            }
            _path = path;

            if (pathParameters != null && pathParameters.Length > 0)
            {
                // initialize internal pathParameters list
                PathParameterCollection parameters = new PathParameterCollection(pathParameters);
                SetPathParameterCollection(parameters);
            }
            PrepareSourceValueInfo(null);
        }
        // "normalize" the path - i.e. load the PathParameters with the early-bound
        // accessors, and replace the corresponding parts of the path with
        // parameter references
        private void NormalizePath()
        {
            StringBuilder           builder    = new StringBuilder();
            PathParameterCollection parameters = new PathParameterCollection();

            for (int i = 0; i < _arySVI.Length; ++i)
            {
                switch (_arySVI[i].drillIn)
                {
                case DrillIn.Always:
                    builder.Append('/');
                    break;

                case DrillIn.Never:
                    if (_arySVI[i].type == SourceValueType.Property)
                    {
                        builder.Append('.');
                    }
                    break;

                case DrillIn.IfNeeded:
                    break;
                }

                switch (_arySVI[i].type)
                {
                case SourceValueType.Property:
                    if (_earlyBoundPathParts[i] != null)
                    {
                        builder.Append('(');
                        builder.Append(parameters.Count.ToString(TypeConverterHelper.InvariantEnglishUS.NumberFormat));
                        builder.Append(')');

                        parameters.Add(_earlyBoundPathParts[i]);
                    }
                    else
                    {
                        builder.Append(_arySVI[i].name);
                    }
                    break;

                case SourceValueType.Indexer:
                    builder.Append('[');
                    if (_earlyBoundPathParts[i] != null)
                    {
                        IndexerParameterInfo[] aryIPI = (IndexerParameterInfo[])_earlyBoundPathParts[i];
                        // the params should be at the very least a single empty string
                        Debug.Assert(aryIPI.Length > 0);
                        int j = 0;
                        while (true)
                        {
                            IndexerParameterInfo info = aryIPI[j];
                            if (info.type != null)
                            {
                                builder.Append('(');
                                builder.Append(parameters.Count.ToString(TypeConverterHelper.InvariantEnglishUS.NumberFormat));
                                builder.Append(')');

                                parameters.Add(info.value);
                            }
                            else
                            {
                                builder.Append(info.value);
                            }
                            ++j;

                            if (j < aryIPI.Length)
                            {
                                builder.Append(',');
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        builder.Append(_arySVI[i].name);
                    }
                    builder.Append(']');
                    break;

                case SourceValueType.Direct:
                    break;
                }
            }

            if (parameters.Count > 0)
            {
                _path = builder.ToString();
                SetPathParameterCollection(parameters);
            }
        }