Share on FacebookOn a project I'm contributor at, the GridViewComboBoxColumn would show a ComboBox in the gridview cell when edit mode was active. But if you switch away to another cell, there would be nothing showing. (When the read only mode of the cell was active, cell was blank). Additionally, the bound column was not receiving any updated information.
Time is always short on these projects so I opted for something quick. Rather than trying to research how to fix my view model, I put in a custom GridViewComboBoxColumn control. Maybe this approach would work for you. Basically code change consists of 1. Add two classes and 2. change your Xaml to reference the custom column instead of Telerik's.
1. Create the custom control which will be embedded within the grid cell. This may be overkill for your project – ours will use the flexibility. We have a read only mode here so that we can show the same contol to the user whether it’s being edited or not.
public class StackPanelWComboBox : StackPanel
{
public ComboBox cb = null;
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String),typeof(StackPanelWComboBox), new PropertyMetadata(TextChanged));
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
StackPanelWComboBox sh = (StackPanelWComboBox)d;
if (sh.cb == null || e.NewValue == null)
return;
sh.cb.SelectedValue = e.NewValue.ToString();
}
public object CommandParameter
{
set{
if (cb == null)
return;
cb.Tag = value;
}
get{
if (cb == null)
return null;
return cb.Tag;
}
}
public StackPanelWComboBox()
{
}
public StackPanelWComboBox(object dataItem, double width, double minwidth, bool readOnly)
{
createContents(dataItem, width, minwidth, readonly);
}
public List<EMC_Class> ABCD
{
get
{
List<EMC_Class> lst = new List<EMC_Class>();
foreach (var x in new EMC_Class[]
{
new EMC_Class { ClassID = 0, ClassName = "NA" },
new EMC_Class { ClassID = 0, ClassName = "A" },
new EMC_Class { ClassID = 1, ClassName = "B" },
new EMC_Class { ClassID = 2, ClassName = "C" },
new EMC_Class { ClassID = 3, ClassName = "D" }
})
{
lst.Add(x);
}
return lst;
}
}
public class EMC_Class
{
public int ClassID { get; set; }
public string ClassName { get; set; }
}
public void createContents(object dataItem, double width, double minwidth, bool readOnly)
{
Children.Clear();
Orientation = Orientation.Horizontal;
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
Grid cbHolder = new Grid();
tb = new ComboBox();
tb.Width = width;
tb.MinWidth = width;
tb.DisplayMemberPath = "ClassName";
tb.SelectedValuePath = "ClassName";
cbHolder.Children.Add(tb);
if (readOnly)
{
Rectangle rect = new Rectangle();
rect.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
rect.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
rect.Fill = Application.Current.Resources["WhiteBrush"] as LinearGradientBrush;
rect.Opacity = 0.2;
cbHolder.Children.Add(rect);
}
Children.Add(cbHolder);
}
}
2. Create the class which will be used in place of GridViewComboBoxColumn: ( it does inherit it though)
public class IWGridViewComboColumn : GridViewComboBoxColumn
{
public String Text
{
get
{
return (String)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text",
typeof(String),
typeof(IWGridViewComboColumn),
new PropertyMetadata(null));
public IWGridViewComboColumn()
{
}
public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
{
base.CreateCellEditElement(cell, dataItem);
var currentcontrol = cell.Content;
if (currentcontrol != null && currentcontrol.GetType() == typeof(ComboBox))
Text = ((ComboBox)currentcontrol).SelectedValue.ToString();
StackPanelWComboBox panel = null;
if (this.DataMemberBinding != null)
{
this.BindingTarget = StackPanelWComboBox.TextProperty;
}
if (panel == null)
{
panel = new StackPanelWComboBox(dataItem, ActualWidth, MinWidth, false);
}
if (this.DataMemberBinding != null)
{
panel.SetBinding(this.BindingTarget, this.CreateValueBinding());
}
panel.Text = Text;
return panel as FrameworkElement;
}
public override FrameworkElement CreateCellElement(GridViewCell cell, object dataItem)
{
base.CreateCellElement(cell, dataItem);
var currentcontrol = cell.Content;
StackPanelWComboBox panel = null;
if (currentcontrol != null)
{
panel = cell.Content as StackPanelWComboBox;
}
if (this.DataMemberBinding != null)
{
this.BindingTarget = StackPanelWComboBox.TextProperty;
}
if (panel == null)
{
panel = new StackPanelWComboBox(dataItem, 90, 90, true);
}
if (this.DataMemberBinding != null)
{
panel.SetBinding(this.BindingTarget, this.CreateValueBinding());
}
panel.Text = dataItem.value;//this will depend on the value of your datatype.
return panel;
}
private Binding CreateValueBinding()
{
var valueBinding = new Binding();
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.NotifyOnValidationError = true;
valueBinding.ValidatesOnExceptions = true;
valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
valueBinding.Path = new PropertyPath(this.DataMemberBinding.Path.Path);
return valueBinding;
}
public override void CopyPropertiesFrom(GridViewColumn source)
{
base.CopyPropertiesFrom(source);
var gridViewEasyEntryTextColumn = source as IWGridViewComboColumn;
if (gridViewEasyEntryTextColumn != null)
{
this.Text = gridViewEasyEntryTextColumn.Text;
}
}
public override IList<ValidationError> UpdateSourceWithEditorValue(GridViewCell gridViewCell)
{
List<ValidationError> errors = new List<ValidationError>();
StackPanelWComboBox editor = gridViewCell.GetEditingElement() as StackPanelWComboBox;
BindingExpression bindingExpression = editor.ReadLocalValue(StackPanelWComboBox.TextProperty) as BindingExpression;
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
errors.AddRange(Validation.GetErrors(editor));
}
return errors;
}
public override object GetNewValueFromEditor(object editor)
{
StackPanelWComboBox panel = editor as StackPanelWComboBox;
if (panel != null)
{
panel.Text = panel.cb.SelectedValue.ToString();
return panel.cb.SelectedValue.ToString();
}
else
{
return null;
}
}
}
4. Add the namespace declaration to your Xaml class.
<UserControl
xmlns:local="clr-namespace:THENAMESPACEOFYOURCONTROL"
5. Trade out the Telerik column in the grid view with your new custom column:
<telerik:RadGridView Height="250"
ShowGroupPanel="True"
VerticalAlignment="Top"
AutoGenerateColumns="False" >
<telerik:RadGridView.Columns>
<local:IWGridViewComboColumn Width="100"
Header="Class"
DisplayMemberPath="ClassName"
SelectedValueMemberPath="ClassID"
DataMemberBinding="{Binding Class}"
ItemsSource = "{Binding ABCD}"
>
That’s it. Hopefully it’s helpful to you.