/// <summary>
        /// Updates the selected attributes to the dictionary.
        /// </summary>
        private void SetSelectedAttributes(TreeNode parent, OpcClientSdk.Ae.TsCAeCategory category, OpcClientSdk.Ae.TsCAeAttributeDictionary attributes)
        {
            foreach (TreeNode child in parent.Nodes)
            {
                if (!typeof(TsCAeAttribute).IsInstanceOfType(child.Tag))
                {
                    continue;
                }

                OpcClientSdk.Ae.TsCAeAttribute attribute = (OpcClientSdk.Ae.TsCAeAttribute)child.Tag;

                if (attributes[category.ID].Contains(attribute.ID))
                {
                    child.Checked = true;
                }
                else
                {
                    child.Checked = false;
                }
            }
        }
        /// <summary>
        /// Displays the notification in the control.
        /// </summary>
        public void ShowNotification(Ae.TsCAeSubscription subscription, TsCAeEventNotification notification)
        {
            // check for null value.
            if (notification == null)
            {
                SourceTB.Text           = "";
                TimeTB.Text             = "";
                MessageTB.Text          = "";
                EventTypeTB.Text        = "";
                EventCategoryTB.Text    = "";
                ConditionNameTB.Text    = "";
                SubConditionNameTB.Text = "";
                NewStateTB.Text         = "";
                AckRequiredTB.Text      = "";
                QualityTB.Text          = "";
                ActiveTimeTB.Text       = "";
                ActorTB.Text            = "";

                AttributesLV.Items.Clear();
                return;
            }

            // find category.
            OpcClientSdk.Ae.TsCAeCategory category = null;

            try
            {
                OpcClientSdk.Ae.TsCAeCategory[] categories = subscription.Server.QueryEventCategories((int)notification.EventType);

                for (int ii = 0; ii < categories.Length; ii++)
                {
                    if (categories[ii].ID == notification.EventCategory)
                    {
                        category = categories[ii];
                        break;
                    }
                }
            }
            catch
            {
                category = null;
            }

            // find attributes.
            ArrayList attributes = new ArrayList();

            try
            {
                // get attribute descriptions.
                OpcClientSdk.Ae.TsCAeAttribute[] descriptions = subscription.Server.QueryEventAttributes(notification.EventCategory);

                // get selected attributes.
                int[] attributeIDs = null;

                if (subscription.Attributes.Contains(notification.EventCategory))
                {
                    attributeIDs = subscription.Attributes[notification.EventCategory].ToArray();
                }

                // find decriptions for selected attributes.
                if (attributeIDs != null)
                {
                    for (int ii = 0; ii < attributeIDs.Length; ii++)
                    {
                        for (int jj = 0; jj < descriptions.Length; jj++)
                        {
                            if (descriptions[jj].ID == attributeIDs[ii])
                            {
                                attributes.Add(descriptions[jj]);
                                break;
                            }
                        }
                    }
                }
            }
            catch
            {
                // ignore errors.
            }

            SourceTB.Text           = notification.SourceID;
            TimeTB.Text             = OpcClientSdk.OpcConvert.ToString(notification.Time);
            MessageTB.Text          = notification.Message;
            EventTypeTB.Text        = OpcClientSdk.OpcConvert.ToString(notification.EventType);
            EventCategoryTB.Text    = (category != null)?category.Name:"";
            ConditionNameTB.Text    = notification.ConditionName;
            SubConditionNameTB.Text = notification.SubConditionName;
            NewStateTB.Text         = "";
            AckRequiredTB.Text      = OpcClientSdk.OpcConvert.ToString(notification.AckRequired);
            QualityTB.Text          = OpcClientSdk.OpcConvert.ToString(notification.Quality);
            ActiveTimeTB.Text       = OpcClientSdk.OpcConvert.ToString(notification.ActiveTime);
            ActorTB.Text            = notification.ActorID;

            // convert state to a string.
            if ((notification.NewState & (int)Ae.TsCAeConditionState.Active) != 0)
            {
                NewStateTB.Text += Ae.TsCAeConditionState.Active.ToString();
            }

            if ((notification.NewState & (int)Ae.TsCAeConditionState.Enabled) != 0)
            {
                if (NewStateTB.Text != "")
                {
                    NewStateTB.Text += " AND ";
                }
                NewStateTB.Text += Ae.TsCAeConditionState.Enabled.ToString();
            }

            if ((notification.NewState & (int)Ae.TsCAeConditionState.Acknowledged) != 0)
            {
                if (NewStateTB.Text != "")
                {
                    NewStateTB.Text += " AND ";
                }
                NewStateTB.Text += Ae.TsCAeConditionState.Acknowledged.ToString();
            }

            // fill attributes list.
            AttributesLV.Items.Clear();

            for (int ii = 0; ii < notification.Attributes.Count; ii++)
            {
                OpcClientSdk.Ae.TsCAeAttribute attribute = (ii < attributes.Count)?(OpcClientSdk.Ae.TsCAeAttribute)attributes[ii]:null;

                ListViewItem item = new ListViewItem((attribute != null)?attribute.Name:"Unknown");

                item.SubItems.Add(OpcClientSdk.OpcConvert.ToString(notification.Attributes[ii]));

                AttributesLV.Items.Add(item);
            }

            AdjustColumns(AttributesLV);
        }