FIX. RadMultiColumnComboBox - AutoFilter does not work in unbound mode
To reproduce drop RadMultiColumnComboBox on a form and use the code below:
public Form1()
{
InitializeComponent();
ThemeResolutionService.AllowAnimations = false;
RadMultiColumnComboBoxElement multiColumnComboElement = this.combo1.MultiColumnComboBoxElement;
multiColumnComboElement.DropDownSizingMode = SizingMode.UpDownAndRightBottom;
multiColumnComboElement.EditorControl.MasterTemplate.AutoGenerateColumns = false;
multiColumnComboElement.EditorControl.AutoGenerateColumns = false;
GridViewTextBoxColumn column1 = new GridViewTextBoxColumn("Item");
column1.HeaderText = "Item";
multiColumnComboElement.Columns.Add(column1);
GridViewTextBoxColumn column2 = new GridViewTextBoxColumn("Description");
column2.HeaderText = "Description";
multiColumnComboElement.Columns.Add(column2);
combo1.DisplayMember = "Description";
combo1.ValueMember = "Item";
this.combo1.AutoSizeDropDownToBestFit = true;
this.combo1.DataSource = GetData();
FilterDescriptor filter = new FilterDescriptor();
filter.PropertyName = this.combo1.DisplayMember;
filter.Operator = FilterOperator.StartsWith;
this.combo1.EditorControl.MasterTemplate.FilterDescriptors.Add(filter);
this.combo1.AutoFilter = true;
this.combo1.MultiColumnComboBoxElement.AutoCompleteMode = AutoCompleteMode.Suggest;
this.combo1.DropDownStyle = RadDropDownStyle.DropDown;
this.combo1.SelectedItem = null;
}
private List<CustomItem> GetData()
{
List<CustomItem> items = new List<CustomItem>();
for (int i = 0; i < 20; i++)
{
CustomItem item = new CustomItem(i, String.Format("This is item number: {0}", i.ToString()));
items.Add(item);
}
return items;
}
}
[Serializable]
public class CustomItem
{
public int Item { get; set; }
public string Description { get; set; }
public CustomItem(int pItem, string pDescription)
{
this.Item = pItem;
this.Description = pDescription;
}
}
Workaround:
1. Enable the animations
ThemeResolutionService.AllowAnimations = true;
or
2. Increase the popup size by one pixel when opening:
void multiColumnComboElement_PopupOpening(object sender, CancelEventArgs e)
{
RadMultiColumnComboBoxElement multiColumnComboElement = (RadMultiColumnComboBoxElement)sender;
multiColumnComboElement.MultiColumnPopupForm.Size = new Size(multiColumnComboElement.MultiColumnPopupForm.Size.Width + 1, multiColumnComboElement.MultiColumnPopupForm.Size.Height);
}
or
3. Turn off the control clipping
((RadHostItem)((MultiColumnComboPopupForm)multiColumnComboElement.MultiColumnPopupForm).SizingGripDockLayout.Children[1]).ClipControl = false;
How to reproduce: check the attached project and video
Workaround: create a custom RadMultiColumnComboBoxElement
Public Class MyRadMultiColumnComboBox
Inherits RadMultiColumnComboBox
Public Overrides Property ThemeClassName As String
Get
Return GetType(RadMultiColumnComboBox).FullName
End Get
Set(value As String)
MyBase.ThemeClassName = value
End Set
End Property
Protected Overrides Function CreateMultiColumnComboBoxElement() As RadMultiColumnComboBoxElement
Return New MyRadMultiColumnComboBoxEleemnt()
End Function
End Class
Class MyRadMultiColumnComboBoxEleemnt
Inherits RadMultiColumnComboBoxElement
Protected Overrides ReadOnly Property ThemeEffectiveType() As Type
Get
Return GetType(RadMultiColumnComboBoxElement)
End Get
End Property
Protected Overrides Sub SetActiveItem(item As String)
Dim rowIndex As Integer = Me.FindItemIndexExact(Text)
If rowIndex <> -1 Then
Me.textBox.SelectionStart = Me.textBox.Text.Length
End If
End Sub
End Class
Currently it is not possible to select multiple rows in RadMultiColumnComboBox.
Workaround: create a custom RadMultiColumnComboBox control with a custom element. You can also check the attached project.
public class MyRadMultiColumnComboBox : RadMultiColumnComboBox
{
public override string ThemeClassName
{
get
{
return typeof(RadMultiColumnComboBox).FullName;
}
}
protected override RadMultiColumnComboBoxElement CreateMultiColumnComboBoxElement()
{
return new MyRadMultiColumnComboBoxElement();
}
}
public class MyRadMultiColumnComboBoxElement : RadMultiColumnComboBoxElement
{
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadMultiColumnComboBoxElement);
}
}
protected override void ProcessKeyDown(object sender, KeyEventArgs e)
{
base.ProcessKeyDown(sender, e);
if (this.IsPopupOpen && (e.KeyCode == Keys.PageDown || e.KeyCode == Keys.PageUp))
{
this.EditorControl.GridBehavior.ProcessKey(e);
}
}
}
When you enable the popup sizing functionality, the last user defined size by the sizing grip should be kept.
To reproduce:
DataTable dt = new DataTable();
for (int i = 0; i < 10; i++)
{
dt.Columns.Add("Column " + i);
}
for (int i = 0; i < 1000; i++)
{
dt.Rows.Add(i);
}
this.radMultiColumnComboBox1.DataSource = dt;
this.radMultiColumnComboBox1.DisplayMember = "Column 0";
this.radMultiColumnComboBox1.DropDownSizingMode = SizingMode.UpDown;
this.radMultiColumnComboBox1.AutoSizeDropDownToBestFit = true;
this.radMultiColumnComboBox1.EditorControl.LoadElementTree();
this.radMultiColumnComboBox1.MultiColumnComboBoxElement.DropDownAnimationEnabled = false;
this.radMultiColumnComboBox1.MultiColumnComboBoxElement.ShowPopup();
The columns are autosized but the popup is not sized correctly.
When you set the DropDownHeight property to a big number that exceeds the screen's height, the applied values is SystemInformation.WorkingArea.Height - 100 . However, it should be only SystemInformation.WorkingArea.Height. These 100 pixels shouldn't be lost.
NOTE: the same behavior is observed with DropDownWidth as well.
Workaround:
Public Class CustomMultiColumn
Inherits RadMultiColumnComboBox
Protected Overrides Function CreateMultiColumnComboBoxElement() As RadMultiColumnComboBoxElement
Return New CustomRadMultiColumnComboBoxElement()
End Function
Public Overrides Property ThemeClassName As String
Get
Return GetType(RadMultiColumnComboBox).FullName
End Get
Set(value As String)
MyBase.ThemeClassName = value
End Set
End Property
End Class
Public Class CustomRadMultiColumnComboBoxElement
Inherits RadMultiColumnComboBoxElement
Protected Overrides Function GetPopupSize(popup As RadPopupControlBase, measure As Boolean) As Drawing.Size
Dim s As Size = MyBase.GetPopupSize(popup, measure)
Return New Size(s.Width, Math.Min(SystemInformation.WorkingArea.Height, Me.DropDownHeight))
End Function
Protected Overrides ReadOnly Property ThemeEffectiveType As Type
Get
Return GetType(RadMultiColumnComboBoxElement)
End Get
End Property
End Class
To reproduce: radMultiColumnComboBox.AutoFilter = True Dim filter As New Telerik.WinControls.Data.FilterDescriptor() filter.PropertyName = radMultiColumnComboBox.DisplayMember filter.Operator = Telerik.WinControls.Data.FilterOperator.StartsWith radMultiColumnComboBox.EditorControl.MasterTemplate.FilterDescriptors.Add(filter) radMultiColumnComboBox.MultiColumnComboBoxElement.AutoCompleteMode = AutoCompleteMode.SuggestAppend radMultiColumnComboBox.MultiColumnComboBoxElement.LimitToList = True - Select an item, copy the text and then try to paste it.
To reproduce:
Create a create a class with Properties Id, Name, ParentId
this.multiColumnComboBox.MultiColumnComboBoxElement
.EditorControl.Relations.AddSelfReference(this.multiColumnComboBox.MultiColumnComboBoxElement.EditorControl.MasterTemplate, "Id", "ParentId");
this.multiColumnComboBox.DataSource = this.people;
this.multiColumnComboBox.DisplayMember = "Name";
this.multiColumnComboBox.ValueMember = "Id";
this.multiColumnComboBox.AutoFilter = true;
this.multiColumnComboBox.DisplayMember = "Name";
FilterDescriptor filter = new FilterDescriptor();
filter.PropertyName = this.multiColumnComboBox.DisplayMember;
filter.Operator = FilterOperator.Contains;
this.multiColumnComboBox.EditorControl.MasterTemplate.FilterDescriptors.Add(filter);
When you open the popup exception should occur.
To reproduce:
Create a ListView or GridView cell element. For example:
public class FilterGroupByCell : DetailListViewDataCellElement
{
private RadMultiColumnComboBoxElement multiColumnComboBox = new RadMultiColumnComboBoxElement();
public FilterGroupByCell(DetailListViewVisualItem owner, ListViewDetailColumn column) :
base(owner, column) { }
protected override void CreateChildElements()
{
base.CreateChildElements();
this.multiColumnComboBox.AutoSizeDropDownToBestFit = true;
multiColumnComboBox.DropDownSizingMode = SizingMode.UpDownAndRightBottom;
multiColumnComboBox.EditorControl.MasterTemplate.AutoGenerateColumns = false;
GridViewTextBoxColumn column = new GridViewTextBoxColumn("CustomerID");
column.HeaderText = "Customer ID";
multiColumnComboBox.Columns.Add(column);
column = new GridViewTextBoxColumn("ContactName");
column.HeaderText = "Contact Name";
multiColumnComboBox.Columns.Add(column);
column = new GridViewTextBoxColumn("ContactTitle");
column.HeaderText = "Contact Title";
multiColumnComboBox.Columns.Add(column);
column = new GridViewTextBoxColumn("Country");
column.HeaderText = "Country";
multiColumnComboBox.Columns.Add(column);
column = new GridViewTextBoxColumn("Phone");
column.HeaderText = "Phone";
multiColumnComboBox.Columns.Add(column);
this.Children.Add(multiColumnComboBox);
}
public override void Synchronize()
{
base.Synchronize();
this.Text = "";
if (base.Row == null)
{
return;
}
this.CurrentFilter = (MFilter)base.Row.DataBoundItem;
if (CurrentFilter.CustomListRecordId == "1")
multiColumnComboBox.Visibility = Telerik.WinControls.ElementVisibility.Collapsed;
DataTable table1 = new DataTable("test");
table1.Columns.Add("CustomerID");
table1.Columns.Add("ContactName");
table1.Columns.Add("ContactTitle");
table1.Columns.Add("Country");
table1.Columns.Add("Phone");
table1.Rows.Add(1, "Ivan Petrov", "2", "2", "2");
table1.Rows.Add(2, "Stefan Muler", "2", "2", "2");
table1.Rows.Add(3, "Alexandro Ricco", "2", "2", "2");
multiColumnComboBox.DataSource = table1;
multiColumnComboBox.DisplayMember = "ContactName";
}
public MFilter CurrentFilter { get; set; }
}
Workaround:
Create a custom RadMultiColumnComboBoxElement:
public class MyRadMultiColumnComboBoxElement : RadMultiColumnComboBoxElement
{
protected override void OnParentChanged(Telerik.WinControls.RadElement previousParent)
{
if (this.IsPopupOpen)
{
this.ClosePopup(RadPopupCloseReason.CloseCalled);
}
if (this.Parent != null && this.Parent.ElementTree != null && this.Parent.ElementTree.Control is RadGridView)
{
base.OnParentChanged(previousParent);
}
}
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadMultiColumnComboBoxElement);
}
}
}
In order to be able to set a DataSource you need to create a new BindingContext prior setting setting the DataSource:
DataTable table1 = new DataTable("test");
table1.Columns.Add("CustomerID");
table1.Columns.Add("ContactName");
table1.Columns.Add("ContactTitle");
table1.Columns.Add("Country");
table1.Columns.Add("Phone");
table1.Rows.Add(1, "Ivan Petrov", "2", "2", "2");
table1.Rows.Add(2, "Stefan Muler", "2", "2", "2");
table1.Rows.Add(3, "Alexandro Ricco", "2", "2", "2");
multiColumnComboBox.EditorControl.BindingContext = new System.Windows.Forms.BindingContext();
multiColumnComboBox.DataSource = table1;
multiColumnComboBox.DisplayMember = "ContactName";
Currently there is not support for simple binding for this property.
To reproduce:
void radMultiColumnComboBox1_SelectedValueChanged(object sender, EventArgs e)
{
MessageBox.Show("test");
}
To reproduce:
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
for (int i = 0; i < 20; i++)
{
dt.Rows.Add(i, "Item" + i);
}
this.radMultiColumnComboBox1.DataSource = dt;
this.radMultiColumnComboBox1.DisplayMember = "Name";
this.radMultiColumnComboBox1.ValueMember = "Id";
this.radMultiColumnComboBox1.SelectedValueChanged += radMultiColumnComboBox1_SelectedValueChanged;
}
private void radMultiColumnComboBox1_SelectedValueChanged(object sender, EventArgs e)
{
if (this.radMultiColumnComboBox1.SelectedIndex > -1)
{
MessageBox.Show("Test");
}
}
NOTE: If you use a RadMessageBox, after showing the message the first time, the popup can't be closed because InvalidOperationException is thrown.
Workaround: show the message box in the RadMultiColumnComboBox.DropDownClosed event.
To reproduce: - Start the attached project and type a value so one item remains in the drop down. - Press Enter - event is not fired. Workaround: Use the DropDownClosed event and check if the value is changed.
To reproduce:
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
for (int i = 0; i < 1; i++)
{
dt.Rows.Add(i, "Item" + i);
}
this.radMultiColumnComboBox1.DataSource = dt;
this.radMultiColumnComboBox1.DisplayMember = "Name";
this.radMultiColumnComboBox1.ValueMember = "Id";
this.radMultiColumnComboBox1.AutoFilter = true;
this.radMultiColumnComboBox1.SelectedIndex = -1;
NOTE: If you add more than 1 items, the text won't be changed.
Workaround:
Public Class CustomRadMultiColumnComboBox
Inherits RadMultiColumnComboBox
Protected Overrides Function CreateMultiColumnComboBoxElement() As RadMultiColumnComboBoxElement
Return New CustomRadMultiColumnComboBoxElement()
End Function
Public Overrides Property ThemeClassName As String
Get
Return GetType(RadMultiColumnComboBox).FullName
End Get
Set(value As String)
MyBase.ThemeClassName = value
End Set
End Property
End Class
Public Class CustomRadMultiColumnComboBoxElement
Inherits RadMultiColumnComboBoxElement
Protected Overrides Sub CheckForCompleteMatchAndUpdateText()
End Sub
Protected Overrides ReadOnly Property ThemeEffectiveType() As Type
Get
Return GetType(RadMultiColumnComboBoxElement)
End Get
End Property
End Class
To reproduce: - The attached video shows how you can reproduce the issue Note - you should type fast in the drop down and the size is invalid only the firs time. Workaround: RadMultiColumnComboBox1.MultiColumnComboBoxElement.DropDownAnimationEnabled = False
To reproduce: - Add 200k rows and the call the BestFitColumns method like this (only the visual rows should be measured in this case): this.radMultiColumnComboBox.BestFitColumns(true, false); Workaround: Set the AutoSizeDropDownColumnMode before calling the method: this.radMultiColumnComboBox.MultiColumnComboBoxElement.AutoSizeDropDownColumnMode = BestFitColumnMode.DisplayedCells; this.radMultiColumnComboBox.BestFitColumns(true, false);
To reproduce:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Random r = new Random();
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
for (int i = 0; i < 10; i++)
{
table.Rows.Add(i, "Row with longer value " + i);
}
radMultiColumnComboBox1.DropDownOpening += radMultiColumnComboBox1_DropDownOpening;
radMultiColumnComboBox1.AutoSizeDropDownToBestFit = true;
radMultiColumnComboBox1.DataSource = table;
}
void radMultiColumnComboBox1_DropDownOpening(object sender, CancelEventArgs args)
{
// radMultiColumnComboBox1.BestFitColumns();
}
private void button1_Click(object sender, EventArgs e)
{
Random r = new Random();
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
for (int i = 0; i < 10; i++)
{
table.Rows.Add(i, "Row " + i);
}
radMultiColumnComboBox1.DataSource = table;
}
}
WORKAROUND: call the BestFitColumns method in the DropDownOpening event