//===================================================================== /// <summary> /// Constructor /// </summary> /// <remarks>By default, the combo box will display all columns in its data source without row or column /// headers, all columns will be auto-sized to the longest item within each column, and auto-completion /// is enabled.</remarks> public MultiColumnComboBox() { this.MouseTracking = true; ddsDropDownFormat = new DropDownTableStyle(); ddsDropDownFormat.GridColumnStyles.CollectionChanged += GridColumnStyles_CollectionChanged; }
//===================================================================== /// <summary> /// Constructor /// </summary> /// <remarks>By default, the combo box will display all columns in its data source without row or column /// headers, all columns will be auto-sized to the longest item within each column, and auto-completion /// is enabled.</remarks> public MultiColumnComboBox() { this.MouseTracking = true; ddsDropDownFormat = new DropDownTableStyle(); ddsDropDownFormat.GridColumnStyles.CollectionChanged += GridColumnStyles_CollectionChanged; }
/// <summary> /// This is used to initialize the drop-down styles and data source /// </summary> private void InitDropDown() { DropDownTableStyle ddts = owner.DropDownFormat; int rowCount, rowHeight, headerHeight = 0, idx = 0, totalSize = 0, rowHeaderWidth = ddts.RowHeaderWidth; // Must check this before we set the data source otherwise, columns are added by default bool autoSize = (ddts.GridColumnStyles.Count == 0); dgDropDown.Font = owner.DropDownFont; dgDropDown.RightToLeft = owner.RightToLeft; this.BackColor = dgDropDown.BackgroundColor = owner.DropDownBackColor; this.Cursor = owner.Cursor; // Set the data source and apply style settings. If there is a data source, use it. ddts.MappingName = owner.MappingName; dgDropDown.DataMember = owner.BindingPath; if (owner.DataSource != null) { // If bound to a relationship, use the object collection if (ddts.MappingName == dgDropDown.DataMember && ddts.MappingName.IndexOf('.') != -1) { ddts.MappingName = "ObjectCollection"; dgDropDown.TableStyles.Add(ddts); dgDropDown.DataSource = owner.Items; } else { dgDropDown.TableStyles.Add(ddts); dgDropDown.DataSource = owner.DataSource; } } else if (ddts.MappingName == "ValueType" || ddts.MappingName == "String") { // Value and string types require a wrapper or they don't show up correctly ValueItem[] viArray = new ValueItem[owner.Items.Count]; for (int collIdx = 0; collIdx < owner.Items.Count; collIdx++) { viArray[collIdx] = new ValueItem(owner.Items[collIdx]); } ddts.MappingName = "ValueItem[]"; dgDropDown.TableStyles.Add(ddts); dgDropDown.DataSource = viArray; } else // It must be an object collection { dgDropDown.DataSource = owner.Items; } // Filter the columns if necessary and clear the headers if auto-sizing and they aren't visible. // Clearing the header text is necessary so that we get an accurate size. StringCollection filter = owner.ColumnFilter; if (filter.Count != 0 || (autoSize && !ddts.ColumnHeadersVisible)) { for (idx = 0; idx < ddts.GridColumnStyles.Count; idx++) { if (filter.Count != 0 && !filter.Contains(ddts.GridColumnStyles[idx].MappingName)) { ddts.GridColumnStyles.RemoveAt(idx); idx--; } else if (autoSize && !ddts.ColumnHeadersVisible) { ddts.GridColumnStyles[idx].HeaderText = String.Empty; } } } // Row Header Width and Column Headers Visible seem to get overridden so restore them ddts.RowHeaderWidth = rowHeaderWidth; dgDropDown.ColumnHeadersVisible = ddts.ColumnHeadersVisible; // Only auto-size if the user didn't specify any columns if (autoSize) { DataGridHelper.AutoSizeColumns(dgDropDown); } // Sum the width of the columns and take the opportunity to auto-size columns with a width of zero. // This only happens if the user specified column definitions. idx = 0; foreach (DataGridColumnStyle col in ddts.GridColumnStyles) { // Replace default null text where needed if (col.NullText == "(null)") { col.NullText = ddts.DefaultNullText; } if (col.Width == 0) { DataGridHelper.AutoSizeColumn(dgDropDown, idx); } totalSize += col.Width; idx++; } // Use the specified width or figure out the initial width if (owner.DropDownWidth != 0) { totalSize = owner.DropDownWidth; } else { if (ddts.RowHeadersVisible) { totalSize += rowHeaderWidth; } if (idx != 0 && totalSize < owner.Width - 2) { // Stretch the last column to fit the width ddts.GridColumnStyles[idx - 1].Width += owner.Width - totalSize - 2; totalSize = owner.Width; } else if (idx == 0) { totalSize = owner.Width; } else { totalSize += 2; } } // Enforce a minimum width if (totalSize < 30) { totalSize = 30; } this.Width = totalSize; // Set default height rowCount = DataGridHelper.RowCount(dgDropDown); if (rowCount != 0 && ddts.GridColumnStyles.Count > 0) { rowHeight = dgDropDown.GetCellBounds(0, 0).Height + 1; } else { rowHeight = dgDropDown.PreferredRowHeight; } // Figure out column header height if visible. This is a little ugly but it works. if (ddts.ColumnHeadersVisible) { while (dgDropDown.HitTest(rowHeaderWidth + 2, headerHeight).Type == DataGrid.HitTestType.ColumnHeader) { headerHeight++; } } if (rowCount > owner.MaxDropDownItems) { rowHeight = (rowHeight * owner.MaxDropDownItems) + headerHeight; // Adjust width to account for the scrollbar this.Width += MultiColumnComboBox.DropDownButtonWidth; } else { rowHeight = (rowHeight * rowCount) + headerHeight; } this.Height = rowHeight + this.Height - dgDropDown.Height; hasInitialized = true; }