void m_DeviceList_OnSelectedItemChanged(object sender, GXSelectedItemEventArgs e)
 {
     if (Director.DirectorPanel.Visible)
     {
         //Enable menus.
         int devCnt = Director.m_DeviceList.DeviceGroups.GetDevicesRecursive().Count;
         bool isDeviceGroupExists = Director.m_DeviceList.DeviceGroups.Count > 0;
         bool IsDeviceListSelected = e.NewItem is GXDeviceList;
         bool IsDeviceGroupSelected = e.NewItem is GXDeviceGroup || e.NewItem is GXDeviceCollection;
         bool Connecting = GXTransactionManager.IsConnecting(e.NewItem);
         bool IsConnected = IsDeviceListSelected || IsDeviceGroupSelected || GXTransactionManager.IsConnected(e.NewItem);
         bool IsMonitoring = IsDeviceListSelected || IsDeviceGroupSelected || GXTransactionManager.IsMonitoring(e.NewItem);
         NewDeviceMenu.Enabled = isDeviceGroupExists && !IsDeviceListSelected;
         //Connect is enabled when device list or device group is selected or device is selected and device is disconnected.			
         ToolsConnectMenu.Enabled = !Connecting && devCnt > 0 && ((IsDeviceListSelected || IsDeviceGroupSelected) || !IsConnected);
         ToolsDisconnectMenu.Enabled = !Connecting && devCnt > 0 && ((IsDeviceListSelected || IsDeviceGroupSelected) || IsConnected);
         ToolsMonitorMenu.Enabled = !Connecting && devCnt > 0 && ((IsDeviceListSelected || IsDeviceGroupSelected) || !IsMonitoring);
         ToolsStopMonitoringMenu.Enabled = !Connecting && devCnt > 0 && ((IsDeviceListSelected || IsDeviceGroupSelected) || IsMonitoring);
         DeleteToolStripButton.Enabled = DeleteMenu.Enabled = (isDeviceGroupExists && (!IsMonitoring || IsDeviceGroupSelected)) && (IsDeviceGroupSelected || e.NewItem is GXDevice);
         WriteToolStripButton.Enabled = ReadToolStripButton.Enabled = ToolsWriteMenu.Enabled = ToolsReadMenu.Enabled = !Connecting && IsConnected && isDeviceGroupExists && devCnt > 0;
         MonitorToolStripButton.Enabled = ConnectToolStripButton.Enabled = !Connecting && devCnt > 0;
         //ConnectToolStripButton.ImageIndex = TransactionManager.IsConnectedMedia(newObject) ? 10 : 4;
         ConnectToolStripButton.Checked = !Connecting && !(IsDeviceListSelected || IsDeviceGroupSelected) && IsConnected;
         MonitorToolStripButton.Checked = !Connecting && ConnectToolStripButton.Checked && IsMonitoring;
     }
 }
        /*
        internal static void SaveDeviceProfiles(GXDeviceProfileCollection list)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.Encoding = System.Text.Encoding.UTF8;
            settings.CloseOutput = true;
            settings.CheckCharacters = false;
            DataContractSerializer x = new DataContractSerializer(typeof(GXDeviceProfileCollection));
            string path = DeviceProfilesPath;
            using (XmlWriter writer = XmlWriter.Create(path, settings))
            {
                x.WriteObject(writer, list);
            }
            Gurux.Common.GXFileSystemSecurity.UpdateFileSecurity(path);
        }

        private static GXDeviceProfileCollection LoadDeviceProfiles()
        {
            GXDeviceProfileCollection items = new GXDeviceProfileCollection(null);
            string TemplatePath = DeviceProfilesPath;
            if (System.IO.File.Exists(TemplatePath))
            {
                DataContractSerializer x = new DataContractSerializer(typeof(GXDeviceProfileCollection));
                using (FileStream reader = new FileStream(TemplatePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    try
                    {
                        items = x.ReadObject(reader) as GXDeviceProfileCollection;
                    }
                    catch (Exception Ex)
                    {
                        System.Diagnostics.Debug.WriteLine(Ex.Message);
                    }
                }
            }
            return items;
        }
         * */

        /// <summary>
        /// CanChangeSelectedItem asks device list clients, if it is OK to change to a new item.
        /// </summary>
        /// <param name="item">Selected item</param>
        /// <returns>True, if selected item can be changed.</returns>
        public bool CanChangeSelectedItem(object item)
        {
            GXSelectedItemEventArgs e = new GXSelectedItemEventArgs(item, m_SelectedItem);
            NotifySelectedItemChanging(e);
            return e.CanChange;
        }
 void NotifySelectedItemChanged(GXSelectedItemEventArgs e)
 {
     if (OnSelectedItemChanged != null)
     {
         OnSelectedItemChanged(this, e);
     }
 }
 void NotifyLoadProgress(GXSelectedItemEventArgs e)
 {
     if (OnLoadProgress != null)
     {
         //OnLoadProgress(this, e);
     }
 }
        /// <summary>
        /// New device has selected. Select device but don't notify it.
        /// </summary>
        public virtual void OnSelectedItemChanged(object sender, GXSelectedItemEventArgs e)
        {
            try
            {
                DeviceListTree.AfterSelect -= new TreeViewEventHandler(OnAfterSelect);
                if (DeviceListTree.SelectedNode != e.NewItem)
                {
                    if (e.NewItem != null)
                    {
                        TreeNode node = (TreeNode)DeviceToTreeNode[e.NewItem];
                        DeviceListTree.SelectedNode = node;
                        if (node != null)
                        {
                            node.EnsureVisible();
                        }
                    }
                    else
                    {
                        DeviceListTree.SelectedNode = null;
                    }
                    bool showDeviceList = e.NewItem is GXDeviceList || e.NewItem is GXDeviceGroup;
                    bool showPropertyList = e.NewItem is GXCategory;
                    bool showPropertyInfo = e.NewItem is GXProperty;
                    GXDevice device = e.NewItem as GXDevice;
                    GXTable table = e.NewItem as GXTable;
                    if (showDeviceList)
                    {
                        DevicesList.Items.Clear();
                        if (e.NewItem is GXDeviceGroup)
                        {
                            GXDeviceGroup group = e.NewItem as GXDeviceGroup;
                            foreach(GXDevice it in group.Devices)
                            {
                                AddDeviceToDeviceList(it);
                            }
                        }
                        else 
                        {
                            GXDeviceList list = e.NewItem as GXDeviceList;
                            foreach (GXDevice it in list.DeviceGroups.GetDevicesRecursive())
                            {
                                AddDeviceToDeviceList(it);
                            }
                        }
                    }
                    else if (showPropertyList)
                    {
                        PropertyList.Items.Clear();
                        GXCategory cat = e.NewItem as GXCategory;
                        List<ListViewItem> items = new List<ListViewItem>();
                        foreach (GXProperty it in cat.Properties)
                        {
                            ListViewItem item = new ListViewItem(it.Name);
                            item.Tag = it;
                            string unit = it.Unit == null ? "" : it.Unit;
                            string type = it.ValueType == null ? "" : it.ValueType.Name;
                            string tm = it.ReadTime == DateTime.MinValue ? "" : it.ReadTime.ToString();
                            object value = it.GetValue(true);
                            if (value is Array || value is IList)
                            {
                                StringBuilder sb = new StringBuilder();
                                if (value is Array)
                                {
                                    Array arr = value as Array;
                                    foreach (object it2 in arr)
                                    {                                        
                                        sb.Append(it2);
                                        sb.Append(", ");
                                    }
                                }
                                else
                                {
                                    IList list = value as IList;
                                    foreach (object it2 in list)
                                    {
                                        sb.Append(it2);
                                        sb.Append(", ");
                                    }
                                }
                                //Remove extra data.
                                if (sb.Length > 2)
                                {
                                    sb.Remove(sb.Length - 2, 2);
                                }
                                value = sb.ToString();
                            }

                            item.SubItems.AddRange(new string[]{Convert.ToString(value), 
                                            type, unit, tm, 
                                            string.Format("{0:#,0}/{1:#,0}", it.Statistics.ReadCount, it.Statistics.ReadFailCount),
                                            string.Format("{0:#,0}/{1:#,0}", it.Statistics.WriteCount, it.Statistics.WriteFailCount),
                                            string.Format("{0:#,0}/{1:#,0}", it.Statistics.ExecutionTime, it.Statistics.ExecutionAverage)});
                            items.Add(item);
                            PropertyToListItem[it] = item;
                        }
                        PropertyList.Items.AddRange(items.ToArray());
                    }
                    else if (showPropertyInfo)
                    {
                        m_Property = e.NewItem as GXProperty;
                        bool write = (m_Property.AccessMode & AccessMode.Write) != 0 && (m_Property.DisabledActions & DisabledActions.Write) == 0;
                        bool read = (m_Property.AccessMode & AccessMode.Read) != 0 && (m_Property.DisabledActions & DisabledActions.Read) == 0;
                        ResetBtn.Enabled = WriteBtn.Enabled = write;
                        ReadBtn.Enabled = read;
                        ValueTB.ReadOnly = !write;
                        NameTB.Text = m_Property.DisplayName;
                        UnitTB.Text = m_Property.Unit;
                        if (m_Property.ValueType != null)
                        {
                            TypeTB.Text = m_Property.ValueType.Name;
                        }
                        else
                        {
                            TypeTB.Text = "Unknown";
                        }
                        // Check type of the property to determine the type of the control used for value input.
                        UseBitMask = m_Property.BitMask;
                        UseCombobox = !UseBitMask && m_Property.Values.Count != 0;
                        ValueCB.Items.Clear();
                        ValueLB.Items.Clear();
                        Type type = m_Property.ValueType;
                        if (type == null)
                        {
                            type = typeof(string);
                        }
                        object value = m_Property.GetValue(true);
                        string str = Convert.ToString(value);                                               
                        if (type == typeof(bool))
                        {
                            ValueCB.Items.Add(bool.FalseString);
                            ValueCB.Items.Add(bool.TrueString);
                            UseCombobox = true;
                        }
                        else if (UseCombobox)
                        {
                            foreach (GXValueItem it in m_Property.Values)
                            {
                                ValueCB.Items.Add(it.UIValue);                            
                            }
                        }
                        if (UseCombobox)
                        {
                            ValueCB.Visible = true;
                            ValueLB.Visible = ValueTB.Visible = false;
                            this.ValueCB.SelectedIndexChanged -= new System.EventHandler(this.ValueCB_SelectedIndexChanged);
                            ValueCB.SelectedIndex = ValueCB.FindStringExact(str);
                            this.ValueCB.SelectedIndexChanged += new System.EventHandler(this.ValueCB_SelectedIndexChanged);
                            if (m_Property.ForcePresetValues || type == typeof(bool))
                            {
                                ValueCB.DropDownStyle = ComboBoxStyle.DropDownList;
                            }
                            else
                            {
                                ValueCB.DropDownStyle = ComboBoxStyle.DropDown;
                                ValueCB.Text = str;
                            }
                        }
                        else
                        {
                            if (value is Array || value is IList)
                            {
                                ValueLB.CheckBoxes = false;
                                ValueLB.Visible = true;
                                ValueCB.Visible = ValueTB.Visible = false;
                                if (value is Array)
                                {
                                    Array arr = value as Array;
                                    foreach (object it in arr)
                                    {
                                        ValueLB.Items.Add(it.ToString());
                                    }
                                }
                                else
                                {
                                    IList list = value as IList;
                                    foreach (object it in list)
                                    {
                                        ValueLB.Items.Add(it.ToString());
                                    }
                                }
                            }
                            else
                            {
                                ValueLB.Visible = ValueCB.Visible = false;
                                if (UseBitMask)
                                {
                                    ValueLB.CheckBoxes = true;
                                    ValueLB.Visible = true;
                                    ulong val = Convert.ToUInt64(m_Property.GetValue(true));
                                    this.ValueLB.ItemCheck -= new System.Windows.Forms.ItemCheckEventHandler(this.ValueLB_ItemCheck);
                                    this.ValueLB.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ValueLB_ItemCheck);
                                }
                                ValueTB.Visible = true;
                                ValueTB.Text = str;
                            }
                        }
                    }
                    else if (device != null)
                    {
                        SelectedDeviceLbl.Text = device.Name;
                        if (string.IsNullOrEmpty(device.Manufacturer))
                        {
                            DeviceTypeTB.Text = device.ProtocolName + " " + device.DeviceProfile;
                        }
                        else
                        {
                            DeviceTypeTB.Text = device.PresetName + " [" + device.Manufacturer + " " + device.Model + " " + device.Version + "]";
                        }
                        DeviceProperties.SelectedObject = device;
                        DeviceMediaFrame.Controls.Clear();
                        Form propertiesForm = device.GXClient.Media.PropertiesForm;
                        ((IGXPropertyPage)propertiesForm).Initialize();
                        while (propertiesForm.Controls.Count != 0)
                        {
                            Control ctr = propertiesForm.Controls[0];
                            if (ctr is Panel)
                            {
                                if (!ctr.Enabled)
                                {
                                    propertiesForm.Controls.RemoveAt(0);
                                    continue;
                                }
                            }
                            DeviceMediaFrame.Controls.Add(ctr);
                        }
                    }
                    else if (table != null)
                    {                        
                        TableData.AllowUserToAddRows = TableData.AllowUserToDeleteRows = TableData.ShowEditingIcon = (table.AccessMode & AccessMode.Write) != 0;
                        UpdatedTableData(this, new GXTableEventArgs(table, TableStates.RowsClear, 0, null));
                        TableData.Columns.Clear();
                        foreach (GXProperty it in table.Columns)
                        {
                            TableData.Columns.Add(it.Name, it.DisplayName);
                        }                        
                        List<object[]> rows = table.GetRows(0, -1, true);
                        OnUpdated(this, new GXTableEventArgs(table, TableStates.RowsAdded, 0, rows));
                        IGXPartialRead partialRead = table as IGXPartialRead;
                        if (table.Columns.Count != 0)
                        {
                            GXProperty prop = table.Columns[0];
                            if (prop.ValueType != typeof(DateTime))
                            {
                                ReadNewValuesCB.Enabled = ReadFromRB.Enabled = ReadLastRB.Enabled = false;
                                partialRead.Type = PartialReadType.All;
                            }
                            else
                            {
                                ReadNewValuesCB.Enabled = ReadFromRB.Enabled = ReadLastRB.Enabled = true;
                            }
                        }
                        ReadingGB.Visible = partialRead != null;
                        if (partialRead != null)
                        {
                            switch (partialRead.Type)
                            {
                                case PartialReadType.New://Read New values.
                                    ReadNewValuesCB.Checked = true;
                                    try
                                    {
                                        if (partialRead.Type != PartialReadType.New || partialRead.Start == null)
                                        {
                                            LastReadValueTP.Text = "";
                                        }
                                        else
                                        {
                                            LastReadValueTP.Text = Convert.ToDateTime(partialRead.Start).ToString();
                                        }
                                    }
                                    catch
                                    {
                                        LastReadValueTP.Text = "";
                                    }
                                    break;
                                case PartialReadType.All://Read all values.
                                    ReadAllRB.Checked = true;
                                    break;
                                case PartialReadType.Last: //Read last n. Days.
                                    ReadLastRB.Checked = true;
                                    ReadLastTB.Text = partialRead.Start.ToString();
                                    break;
                                case PartialReadType.Range://Read between days
                                    ReadFromRB.Checked = true;
                                    if (partialRead.Start != null)
                                    {
                                        StartPick.Value = Convert.ToDateTime(partialRead.Start);
                                        StartPick.Checked = true;
                                    }
                                    else
                                    {
                                        StartPick.Checked = false;
                                    }
                                    if (partialRead.End != null)
                                    {
                                        ToPick.Value = Convert.ToDateTime(partialRead.End);
                                        ToPick.Checked = true;
                                    }
                                    else
                                    {
                                        ToPick.Checked = false;
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    TablePanel.Visible = table != null;
                    DevicePanel.Visible = device != null;
                    DevicesList.Visible = showDeviceList;
                    PropertyList.Visible = showPropertyList;
                    PropertyPanel.Visible = showPropertyInfo;
                    //Show diagnostics trace.
                    if (TraceLevel != System.Diagnostics.TraceLevel.Off)
                    {
                        if (!TabControl1.TabPages.Contains(TracePage))
                        {
                            TabControl1.TabPages.Add(TracePage);
                        }
                        //If user changes device or device group.
                        device = GXTransactionManager.GetDevice(e.NewItem);
                        if (device == null || device != TracedDevice)
                        {
                            lock (TraceEvents)
                            {
                                TraceEvents.Clear();
                                TraceView.VirtualListSize = 0;
                            }
                            if (TracedDevice != null)
                            {
                                TracedDevice.OnTrace -= new TraceEventHandler(OnTrace);
                            }
                            TracedDevice = null;
                        }
                        //If new device is selected.
                        if (device != null && device != TracedDevice)
                        {
                            TracedDevice = device;
                            TracedDevice.OnTrace += new TraceEventHandler(OnTrace);
                        }
                    }
                    else if (TabControl1.TabPages.Contains(TracePage))
                    {
                        TabControl1.TabPages.Remove(TracePage);
                    }
                }
            }
            catch (Exception Ex)
            {
                GXCommon.ShowError(this.ParentComponent, Gurux.DeviceSuite.Properties.Resources.GuruxDeviceSuiteTxt, Ex);
            }
            finally
            {
                DeviceListTree.AfterSelect += new TreeViewEventHandler(OnAfterSelect);
            }
        }