/// <summary>
        ///     Called when the value needs to be edited.
        /// </summary>
        /// <param name="context">Context of editing.</param>
        /// <param name="provider">Provider of editing.</param>
        /// <param name="value">Original value to edit.</param>
        /// <returns>Edited version of original value.</returns>
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            _editorValue = value as FileEditorValue;
            if (_editorValue == null) return base.EditValue(context, provider, value);

            OpenFileDialog fileWindow = new OpenFileDialog();
            if (_editorValue.Filter != "") fileWindow.Filter = _editorValue.Filter;
            if (_editorValue.FileUrl != "" && File.Exists(_editorValue.FileUrl)) fileWindow.FileName = _editorValue.FileUrl;
            if (_editorValue.BaseDir != "") fileWindow.InitialDirectory = _editorValue.BaseDir;
            fileWindow.FileOk += new CancelEventHandler(fileWindow_FileOk);
            fileWindow.RestoreDirectory = true;
            if (fileWindow.ShowDialog() == DialogResult.OK)
            {
                _editorValue.FileUrl = fileWindow.FileName;
                string baseDir = _editorValue.BaseDir;
                if (baseDir == "") baseDir = Engine.GlobalInstance.GamePath;

                if (baseDir != "" && _editorValue.FileUrl.ToLower().StartsWith(baseDir.ToLower()) == true)
                    _editorValue.FileUrl = _editorValue.FileUrl.Substring(baseDir.Length + 1);

                // We've got to create a new file editor value or the
                // property grid will play up.
                FileEditorValue newValue = new FileEditorValue(_editorValue.FileUrl, _editorValue.Filter, _editorValue.BaseDir);
                _editorValue = newValue;
                return newValue;
            }

            return base.EditValue(context, provider, value);
        }
        /// <summary>
        ///     Called when the value needs to be edited.
        /// </summary>
        /// <param name="context">Context of editing.</param>
        /// <param name="provider">Provider of editing.</param>
        /// <param name="value">Original value to edit.</param>
        /// <returns>Edited version of original value.</returns>
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            _editorValue = value as FileEditorValue;
            if (_editorValue == null)
            {
                return(base.EditValue(context, provider, value));
            }

            OpenFileDialog fileWindow = new OpenFileDialog();

            if (_editorValue.Filter != "")
            {
                fileWindow.Filter = _editorValue.Filter;
            }
            if (_editorValue.FileUrl != "" && File.Exists(_editorValue.FileUrl))
            {
                fileWindow.FileName = _editorValue.FileUrl;
            }
            if (_editorValue.BaseDir != "")
            {
                fileWindow.InitialDirectory = _editorValue.BaseDir;
            }
            fileWindow.FileOk          += new CancelEventHandler(fileWindow_FileOk);
            fileWindow.RestoreDirectory = true;
            if (fileWindow.ShowDialog() == DialogResult.OK)
            {
                _editorValue.FileUrl = fileWindow.FileName;
                string baseDir = _editorValue.BaseDir;
                if (baseDir == "")
                {
                    baseDir = Engine.GlobalInstance.GamePath;
                }

                if (baseDir != "" && _editorValue.FileUrl.ToLower().StartsWith(baseDir.ToLower()) == true)
                {
                    _editorValue.FileUrl = _editorValue.FileUrl.Substring(baseDir.Length + 1);
                }

                // We've got to create a new file editor value or the
                // property grid will play up.
                FileEditorValue newValue = new FileEditorValue(_editorValue.FileUrl, _editorValue.Filter, _editorValue.BaseDir);
                _editorValue = newValue;
                return(newValue);
            }

            return(base.EditValue(context, provider, value));
        }
        /// <summary>
        ///		Syncronizes the data in property list with that contained in the entity.
        /// </summary>
        public void SyncronizeData()
        {
            // Clear the list view so its ready for some new items.
            propertyListView.Clear();

            // If we have no entity at the moment then just disable this control and return.
            if (_entity == null)
            {
                propertyListView.Enabled = false;
                _categories = null;
                propertyListView.Refresh();
                return;
            }

            // Set the default values of this list view.
            propertyListView.Enabled = true;
            propertyListView.DefaultItem = "Test";

            // Split up the color of our entity to make the rendering category
            // easier to create.
            int a, r, g, b;
            ColorMethods.SplitColor(ColorFormats.A8R8G8B8, _entity.Color, out r, out g, out b, out a);

            // Create a list of categories and properties to go in them.
            _categories = new object[]
            {
                // This is our general category.
                new object[]
                {
                    new PropertyListViewCategory("General"),
                    new PropertyListViewItem("Name", _entity.Name, "", "Name of this entity. Used by the event system to identify and trigger this entity if neccessary.", typeof(string)),
                    new PropertyListViewItem("Event", _entity.Event, "", "Name of entity to trigger when this entity is triggered.", typeof(string)),
                    new PropertyListViewItem("Enabled", _entity.IsEnabled, true, "Indicates whether this entity is enabled.", typeof(bool)),
                },

                // This is our transformation category.
                new object[]
                {
                    new PropertyListViewCategory("Transformation"),
                    new PropertyListViewItem("Location", new Point((int)_entity.Transformation.X, (int)_entity.Transformation.Y), new Point(), "The location of this entity.", typeof(Point)),
                    new PropertyListViewItem("Z-Offset", _entity.Transformation.Z, 0.0f, "This value is added to this entities resulting depth, you can use it to set a depth origin.", typeof(float)),
                    new PropertyListViewItem("Z-Layer", _entity.DepthLayer, 0, "Determines which depth layer this entity is render one.", typeof(int)),
                    new PropertyListViewItem("Depth Mode", _entity.DepthMode, (int)EntityDepthMode.Normal, "Determines how the depth of this entity is worked out.", typeof(EntityDepthMode)),
                    new PropertyListViewItem("Scale", new Vector(_entity.Transformation.ScaleX, _entity.Transformation.ScaleY, _entity.Transformation.ScaleZ), new Vector(), "The scale of this entity.", typeof(Vector)),
                    new PropertyListViewItem("Angle", new Vector(_entity.Transformation.AngleX, _entity.Transformation.AngleY, _entity.Transformation.AngleZ), new Vector(), "The rotational angle of this entity in degrees.", typeof(Vector)),
                    new PropertyListViewItem("Bounding Rectangle", _entity.BoundingRectangle, new Rectangle(0,0,0,0), "The bounding box of this entity. The bounding box is used for determining how an entity should be culled to save rendering time.", typeof(Rectangle)),
                },
            };

            // See if we can insert the collision group.
            if (_entity.CollisionPolygon != null)
            {
                 object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                {
                    new PropertyListViewCategory("Collision"),
                    new PropertyListViewItem("Solid", _entity.IsSolid, true, "Indicates whether this entity can respond to collisions.", typeof(bool)),
                    new PropertyListViewItem("Collision Layers", _entity.CollisionPolygon.Layers, new int[] { 0 }, "Indicates which collision layers this entity can collide with.", typeof(int[])),
                    new PropertyListViewItem("Collision Rectangle", _entity.CollisionRectangle, new Rectangle(0,0,0,0), "Specifies the dimensions of the collision box of this entity.", typeof(Rectangle)),
                };
            }

            // Add the text and rendering categories as well.
            if (!(_entity is TilemapSegmentNode) && !(_entity is EmitterNode))
            {
                object[] newCategories = new object[_categories.Length + 2];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                {
                    new PropertyListViewCategory("Rendering"),
                    new PropertyListViewItem("Visible", _entity.IsVisible, true, "Indicates whether this entity is visible.", typeof(bool)),
                    new PropertyListViewItem("Color", Color.FromArgb(ColorMethods.CombineColor(ColorFormats.A8R8G8B8, r, g, b, 255)), Color.FromArgb(unchecked((int)0xFFFFFFFF)), "Indicates the color this entity should be tinted.", typeof(Color)),
                    new PropertyListViewItem("Alpha", a, (byte)255, "Indicates the transparency this entity should be rendered at.", typeof(byte)),
                    new PropertyListViewItem("Blend Mode", _entity.BlendMode, BlendMode.Alpha, "Indicates the blending mode this entity should be rendered with.", typeof(BlendMode)),
                    new PropertyListViewItem("Render Mode", _entity.RenderMode, EntityRenderMode.None, "Indicates how this entity should be rendered.", typeof(EntityRenderMode)),
                    new PropertyListViewItem("Image", _entity.Image, null, "The image that should be rendered if this entitys rendering mode is set to render an image.", typeof(string), typeof(ImageEditor)),
                    new PropertyListViewItem("Frame", _entity.Frame, 0, "The frame of this entitys image that should be rendered when render mode is set to an image mode.", typeof(int)),
                    new PropertyListViewItem("Shader", new FileEditorValue(_entity.Shader == null ? "" : _entity.Shader.URL.ToString(), "Fusion Shader Files|*.xml", Environment.CurrentDirectory +"\\"+ Engine.Engine.GlobalInstance.ShaderPath), null, "The shader that this entity should apply to itself when rendering.", typeof(string), typeof(FileEditor)),
                    new PropertyListViewItem("Mesh", new FileEditorValue(_entity.Mesh == null ? "" : _entity.Mesh.URL.ToString(), "Mesh Files|*.raw", Environment.CurrentDirectory +"\\"+ Engine.Engine.GlobalInstance.MediaPath), null, "The mesh that this entity should use to render if its render mode is set to MESH.", typeof(string), typeof(FileEditor)),
                };

               // ((PropertyListViewItem)(((object[])_categories[_categories.Length - 1])[6])).Attributes = new Attribute[] { new ReadOnlyAttribute(true) };

                // This is our text category.
                _categories[_categories.Length - 2] = new object[]
                {
                    new PropertyListViewCategory("Text"),
                    new PropertyListViewItem("Text", _entity.Text, "", "The string of text that this entity should render if its render mode is set to Text.", typeof(string)),
                    new PropertyListViewItem("Bitmap Font", _entity.Font, null, "Bitmap font used to render text when this entitys render mode is set to Text.", typeof(string), typeof(BitmapFontEditor)),
                };

               // ((PropertyListViewItem)(((object[])_categories[_categories.Length - 2])[2])).Attributes = new Attribute[] { new ReadOnlyAttribute(true) };
            }
            else if (_entity is TilemapSegmentNode)
            {
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                {
                    new PropertyListViewCategory("Rendering"),
                    new PropertyListViewItem("Visible", _entity.IsVisible, true, "Indicates whether this entity is visible.", typeof(bool)),
                    new PropertyListViewItem("Color", Color.FromArgb(ColorMethods.CombineColor(ColorFormats.A8R8G8B8, r, g, b, 255)), Color.FromArgb(unchecked((int)0xFFFFFFFF)), "Indicates the color this entity should be tinted.", typeof(Color)),
                    new PropertyListViewItem("Alpha", a, (byte)255, "Indicates the transparency this entity should be rendered at.", typeof(byte)),
                    new PropertyListViewItem("Blend Mode", _entity.BlendMode, BlendMode.Alpha, "Indicates the blending mode this entity should be rendered with.", typeof(BlendMode)),
                };
            }
            else if (_entity is EmitterNode)
            {
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                {
                    new PropertyListViewCategory("Rendering"),
                    new PropertyListViewItem("Visible", _entity.IsVisible, true, "Indicates whether this entity is visible.", typeof(bool)),
                };
            }

            // Specialist properties.
            if (_entity is ScriptedEntityNode)
            {
                #region Script properties

                // Add the new dynamic category to the category list.
                ArrayList categoryList = new ArrayList();
                categoryList.Add(new PropertyListViewCategory("Script"));
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;

                // Insert all the properties contained in the scripts.
                ScriptedEntityNode scriptedEntity = (ScriptedEntityNode)_entity;
                foreach (Symbol symbol in scriptedEntity.ScriptProcess.GlobalScope.Symbols)
                {
                    if (symbol is VariableSymbol && ((VariableSymbol)symbol).IsProperty == true)
                    {
                        VariableSymbol variableSymbol = ((VariableSymbol)symbol);
                        object value = null;

                        if (variableSymbol.DataType.IsArray == false)
                        {
                            switch (variableSymbol.DataType.DataType)
                            {
                                case DataType.Bool: value = scriptedEntity.ScriptProcess[0].GetBooleanGlobal(variableSymbol.Identifier); break;
                                case DataType.Byte: value = scriptedEntity.ScriptProcess[0].GetByteGlobal(variableSymbol.Identifier); break;
                                case DataType.Double: value = scriptedEntity.ScriptProcess[0].GetDoubleGlobal(variableSymbol.Identifier); break;
                                case DataType.Float: value = scriptedEntity.ScriptProcess[0].GetFloatGlobal(variableSymbol.Identifier); break;
                                case DataType.Int: value = scriptedEntity.ScriptProcess[0].GetIntegerGlobal(variableSymbol.Identifier); break;
                                case DataType.Long: value = scriptedEntity.ScriptProcess[0].GetLongGlobal(variableSymbol.Identifier); break;
                                case DataType.Short: value = scriptedEntity.ScriptProcess[0].GetShortGlobal(variableSymbol.Identifier); break;
                                case DataType.String:
                                    value = scriptedEntity.ScriptProcess[0].GetStringGlobal(variableSymbol.Identifier);
                                    if (value == null) value = "";
                                    break;
                                case DataType.Object:
                                    value = scriptedEntity.ScriptProcess[0].GetObjectGlobal(variableSymbol.Identifier);
                                    if (value is NativeObject)
                                        value = ((NativeObject)value).Object;
                                    break;
                                //default: continue;
                            }
                        }
                        else
                        {
                            int arrayIndex = scriptedEntity.ScriptProcess[0].GetArrayGlobal(variableSymbol.Identifier);
                            int arrayLength = 0;
                            if (arrayIndex == 0)
                                arrayLength = 1;
                            else
                                arrayLength = scriptedEntity.ScriptProcess[0].GetArrayLength(arrayIndex);

                            switch (variableSymbol.DataType.DataType)
                            {
                                case DataType.Bool: value = new bool[arrayLength]; break;
                                case DataType.Byte: value = new byte[arrayLength]; break;
                                case DataType.Double: value = new double[arrayLength]; break;
                                case DataType.Float: value = new float[arrayLength]; break;
                                case DataType.Int: value = new int[arrayLength]; break;
                                case DataType.Long: value = new long[arrayLength]; break;
                                case DataType.Short: value = new short[arrayLength]; break;
                                case DataType.String: value = new string[arrayLength]; break;
                                case DataType.Object: value = new object[arrayLength]; break;
                            }

                            if (arrayIndex != 0)
                            {
                                for (int i = 0; i < arrayLength; i++)
                                {
                                    switch (variableSymbol.DataType.DataType)
                                    {
                                        case DataType.Bool: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetBooleanArrayElement(arrayIndex, i); break;
                                        case DataType.Byte: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetByteArrayElement(arrayIndex, i); break;
                                        case DataType.Double: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetDoubleArrayElement(arrayIndex, i); break;
                                        case DataType.Float: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetFloatArrayElement(arrayIndex, i); break;
                                        case DataType.Int: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetIntArrayElement(arrayIndex, i); break;
                                        case DataType.Long: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetLongArrayElement(arrayIndex, i); break;
                                        case DataType.Short: ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetShortArrayElement(arrayIndex, i); break;
                                        case DataType.String:
                                            ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetStringArrayElement(arrayIndex, i);
                                            if (((object[])value)[i] == null) ((object[])value)[i] = "";
                                            break;
                                        case DataType.Object:
                                            ((object[])value)[i] = scriptedEntity.ScriptProcess[0].GetObjectArrayElement(arrayIndex, i);
                                            if (((object[])value)[i] is NativeObject)
                                                ((object[])value)[i] = ((NativeObject)value).Object;
                                            break;
                                        //default: continue;
                                    }
                                }
                            }
                        }

                        // Check to see if there is an editmethod meta-data chunk attached to this property.
                        string editMethod = "", basePath = "", filter = "", description = "", name = variableSymbol.Identifier, enumeration = "";
                        bool dontCreate = false;
                        Type type = null, editorType = null;
                        foreach (Symbol subSymbol in symbol.Symbols)
                            if (subSymbol is MetaDataSymbol)
                                switch (((MetaDataSymbol)subSymbol).Identifier.ToLower())
                                {
                                    case "editmethod": editMethod = ((MetaDataSymbol)subSymbol).Value; break;
                                    case "basepath": basePath = Environment.CurrentDirectory +"\\"+ ((MetaDataSymbol)subSymbol).Value; break;
                                    case "filter": filter = ((MetaDataSymbol)subSymbol).Value; break;
                                    case "description": description = ((MetaDataSymbol)subSymbol).Value; break;
                                    case "name": name = ((MetaDataSymbol)subSymbol).Value; break;
                                    case "enumeration": enumeration = ((MetaDataSymbol)subSymbol).Value; break;
                                    case "filtertype":
                                        switch (((MetaDataSymbol)subSymbol).Value.ToLower())
                                        {
                                            case "audio": filter = "Audio Files|*.ogg;*.wav"; break;
                                            case "script": filter = "Script Files|*.fs;*.fso;*.fsl"; break;
                                            case "object": filter = "Object Declaration Files|*.fso"; break;
                                            case "font": filter = "Font Declaration Files|*.xml"; break;
                                            case "map": filter = "Fusion Map Files|*.fmp"; break;
                                            case "graphic": filter = "Graphics Files|*.tga;*.bmp"; break;
                                            case "tileset": filter = "Tileset Declaration Files|*.xml"; break;
                                            case "save": filter = "Fusion Save Files|*.fsv"; break;
                                            case "shader": filter = "Fusion Shader Files|*.xml"; break;
                                        }
                                        break;
                                }

                        if (editMethod.ToLower() == "file" && variableSymbol.DataType.DataType == DataType.String)
                        {
                            value = new FileEditorValue(value.ToString(), filter, basePath);
                            type = typeof(string);
                            editorType = typeof(FileEditor);
                        }
                        else if (editMethod.ToLower() == "color" && value is int)
                        {
                            value = Color.FromArgb((int)value);
                            type = typeof(Color);
                        }
                        else if (editMethod.ToLower() == "image" && variableSymbol.DataType.DataType == DataType.Object)
                        {
                            type = typeof(string);
                            editorType = typeof(ImageEditor);
                        }
                        else if (editMethod.ToLower() == "sound" && variableSymbol.DataType.DataType == DataType.Object)
                        {
                            type = typeof(string);
                            editorType = typeof(SoundEditor);
                        }
                        else if (editMethod.ToLower() == "enumeration" && variableSymbol.DataType.DataType == DataType.Int)
                        {
                            // Split up the enumeration scope.
                            string[] scopeList = enumeration.Split(new char[] { '.' });
                            Symbol currentScope = scriptedEntity.ScriptProcess.GlobalScope;

                            // Lets find the correct enumeration.
                            for (int i = 0; i < scopeList.Length; i++)
                            {
                                if (currentScope == null)
                                    break;

                                string scopeName = scopeList[i];
                                currentScope = currentScope.FindSymbol(scopeName);
                            }

                            // Check it exists and is an enumeration.
                            if (currentScope != null && currentScope.Type == SymbolType.Enumeration)
                            {
                                ArrayList list = new ArrayList();
                                PropertyEnumerationEntry currentEntry = null;
                                foreach (Symbol subSymbol in currentScope.Symbols)
                                {
                                    if (subSymbol == null || subSymbol.Type != SymbolType.Variable) continue;
                                    PropertyEnumerationEntry entry = new PropertyEnumerationEntry(subSymbol.Identifier, Int32.Parse(((VariableSymbol)subSymbol).ConstToken.Ident));
                                    if (entry.Value == (int)value) currentEntry = entry;
                                    list.Add(entry);
                                }

                                int index = (int)value;
                                value = (currentEntry == null) ? "Unknown" : currentEntry.Name;
                                type = typeof(string);

                                PropertyListViewItem item = new PropertyListViewItem(name, value, value, description, type);
                                item.EnumerationValues = list;
                                item.EnumerationValue = (currentEntry == null) ? 0 : currentEntry.Value;
                                item.TypeConverter = typeof(PropertyEnumerationConverter).AssemblyQualifiedName;
                                dontCreate = true;
                                categoryList.Add(item);
                            }
                        }
                        else
                        {
                            if (variableSymbol.DataType.DataType == DataType.Object)
                                continue;
                            type = value.GetType();
                        }

                        // And finally lets create the property item.
                        if (dontCreate == false)
                        {
                            if (editorType == null)
                                categoryList.Add(new PropertyListViewItem(name, value, value, description, type));
                            else
                                categoryList.Add(new PropertyListViewItem(name, value, value, description, type, editorType));
                        }
                    }
                }

                // Add everything to the category list.
                _categories[_categories.Length - 1] = categoryList.ToArray();
                #endregion
            }

            else if (_entity is EmitterNode)
            {
                // Add the new dynamic category to the category list.
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                    {
                        new PropertyListViewCategory("Emitter"),
                        new PropertyListViewItem("Effect", _entity, null, "Contains the actual definition of this emitters effect. Editing this will caused the effects editor to be opened.", typeof(string), typeof(EmitterEditor)),
                    };

                //((PropertyListViewItem)(((object[])_categories[_categories.Length - 1])[1])).Attributes = new Attribute[] { new ReadOnlyAttribute(true) };
            }

            else if (_entity is TilemapSegmentNode)
            {
                TilemapSegmentNode segmentNode = _entity as TilemapSegmentNode;

                // Add the new dynamic category to the category list.
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                    {
                        new PropertyListViewCategory("Tilemap"),
                        new PropertyListViewItem("Grid Visible", segmentNode.IsGridVisible, false, "Indicates if a grid should be rendered over this tilemap segment or not.", typeof(bool)),
                        new PropertyListViewItem("Tile Size", new Size(segmentNode.TileWidth, segmentNode.TileHeight), new Size(0,0), "Indicates if a grid should be rendered over this tilemap segment or not.", typeof(Size)),
                    };
            }

            else if (_entity is PathMarkerNode)
            {
                PathMarkerNode markerNode = _entity as PathMarkerNode;

                // Add the new dynamic category to the category list.
                object[] newCategories = new object[_categories.Length + 1];
                _categories.CopyTo(newCategories, 0);
                _categories = newCategories;
                _categories[_categories.Length - 1] = new object[]
                    {
                        new PropertyListViewCategory("Path Marker"),
                        new PropertyListViewItem("Speed", markerNode.Speed, new StartFinishF(0,0), "Indicates the starting and finishing speeds a entity should move along this path.", typeof(StartFinishF)),
                        new PropertyListViewItem("Delay", markerNode.Delay, 0, "If set this indicates the delay before this part of the path starts.", typeof(int)),
                        new PropertyListViewItem("Next Marker Name", markerNode.NextNodeName, "", "This is the name of the next node in the sequence.", typeof(string)),

                    };
                ((PropertyListViewItem)((object[])_categories[_categories.Length - 1])[1]).TypeConverter = typeof(ExpandableObjectConverter).AssemblyQualifiedName;
            }

            // Populate the list view.
            foreach (object[] category in _categories)
            {
                // Create the category.
                PropertyListViewCategory listViewCategory = category[0] as PropertyListViewCategory;
                propertyListView.AddCategory(listViewCategory);

                // Add any existing items into the category.
                if (category.Length > 0)
                    for (int i = category.Length - 1; i >= 1; i--) // Add items in reverse otherwise it will appear the wrong way round :D.
                        listViewCategory.AddProperty((PropertyListViewItem)category[i]);
            }

            // Refresh the property list view.
            propertyListView.Refresh();
        }