Copy/Paste DisplayMember for GridViewComboBoxColumn
Product Version | Product | Author | Last modified |
---|---|---|---|
Q2 2014 | RadGridView for WinForms | Desislava Yordanova | August 22, 2014 |
Problem
By default, the RadGridView built-in copy/paste functionality uses the selected cells’ value when storing data in the Clipboard. However, when you have a GridViewComboBoxColumn it is more suitable to copy/paste the cells’ text.
Solution
MasterGridViewTemplateintroduces two methods appropriate for customizing the Clipboard data: Copyand Paste.
To achieve the desired functionality you should create a derivative of the MasterGridViewTemplateand override its Copy method, where the Clipboard content can be modified:
public class CustomMasterGridViewTemplate : MasterGridViewTemplate
{
public override void Copy()
{
base.Copy();
if (Clipboard.ContainsData(DataFormats.Text)) {
string data = Clipboard.GetData(DataFormats.Text).ToString();
if (data != string.Empty) {
StringBuilder sb = new StringBuilder();
//modify the copied data and replace it in the clipboard
foreach (GridViewRowInfo row in this.Owner.SelectedRows) {
int i = 0;
while (i < row.Cells.Count) {
if (i > 0) {
sb.Append(";");
}
string cellText = null;
GridViewComboBoxColumn comboCol = row.Cells(i).ColumnInfo as GridViewComboBoxColumn;
if (comboCol != null) {
//copy the DisplayMember
cellText = comboCol.GetLookupValue(row.Cells(i).Value);
} else {
cellText = row.Cells(i).Value + string.Empty;
}
sb.Append(cellText);
i += 1;
}
sb.AppendLine();
}
Clipboard.SetData(DataFormats.Text, sb.ToString());
}
}
}
}
Public Class CustomMasterGridViewTemplate
Inherits MasterGridViewTemplate
Public Overrides Sub Copy()
MyBase.Copy()
If Clipboard.ContainsData(DataFormats.Text) Then
Dim data As String = Clipboard.GetData(DataFormats.Text).ToString()
If data <> String.Empty Then
Dim sb As New StringBuilder()
'modify the copied data and replace it in the clipboard
For Each row As GridViewRowInfo In Me.Owner.SelectedRows
Dim i As Integer = 0
While i < row.Cells.Count
If i > 0 Then
sb.Append(";")
End If
Dim cellText As String
Dim comboCol As GridViewComboBoxColumn = TryCast(row.Cells(i).ColumnInfo, GridViewComboBoxColumn)
If comboCol IsNot Nothing Then
'copy the DisplayMember
cellText = comboCol.GetLookupValue(row.Cells(i).Value)
Else
cellText = row.Cells(i).Value & String.Empty
End If
sb.Append(cellText)
i += 1
End While
sb.AppendLine()
Next
Clipboard.SetData(DataFormats.Text, sb.ToString())
End If
End If
End Sub
End Class
Overriding the Paste method allows you to convert the Clipboard data to format appropriate for RadGridView. Thus, copying the above data from Notepad and pasting it to RadGridView can be achieved.
public override void Paste()
{
if (Clipboard.ContainsData(DataFormats.Text))
{
string data = Clipboard.GetData(DataFormats.Text).ToString();
if (data != string.Empty)
{
StringBuilder sb = new StringBuilder();
string[] rowTokens = data.Split(new string[] { Environment.NewLine.ToString() }, StringSplitOptions.RemoveEmptyEntries);
foreach (string rowToken in rowTokens)
{
string[] tokens = rowToken.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < tokens.Length; i++)
{
GridViewComboBoxColumn comboColumn = this.Owner.Columns[i] as GridViewComboBoxColumn;
if (i < this.Owner.Columns.Count && comboColumn != null)
{
//get the ValueMember
sb.Append(GetValueMember(tokens[i], comboColumn.DataSource));
}
else
{
sb.Append(tokens[i]);
}
if (i < tokens.Length - 1)
{
sb.Append("\t");
}
}
sb.Append(Environment.NewLine.ToString());
}
Clipboard.SetData(DataFormats.Text, sb.ToString());
}
}
base.Paste();
}
private string GetValueMember(string token, object source)
{
IEnumerable<Country> dataSource = source as IEnumerable<Country>;
if (dataSource != null)
{
foreach (Country c in dataSource)
{
if (c.Name == token)
{
return c.ID.ToString();
}
}
}
return string.Empty;
}
Public Overrides Sub Paste()
If Clipboard.ContainsData(DataFormats.Text) Then
Dim data As String = Clipboard.GetData(DataFormats.Text).ToString()
If data <> String.Empty Then
Dim sb As New StringBuilder()
Dim rowTokens As String() = data.Split(New String() {Environment.NewLine.ToString()}, StringSplitOptions.RemoveEmptyEntries)
For Each rowToken As String In rowTokens
Dim tokens As String() = rowToken.Split(New Char() {";"c}, StringSplitOptions.RemoveEmptyEntries)
For i As Integer = 0 To tokens.Length - 1
Dim comboColumn As GridViewComboBoxColumn = TryCast(Me.Owner.Columns(i), GridViewComboBoxColumn)
If i < Me.Owner.Columns.Count AndAlso comboColumn IsNot Nothing Then
'get the ValueMember
sb.Append(GetValueMember(tokens(i), comboColumn.DataSource))
Else
sb.Append(tokens(i))
End If
If i < tokens.Length - 1 Then
sb.Append(vbTab)
End If
Next
sb.Append(Environment.NewLine.ToString())
Next
Clipboard.SetData(DataFormats.Text, sb.ToString())
End If
End If
MyBase.Paste()
End Sub
Private Function GetValueMember(token As String, source As Object) As String
Dim dataSource As IEnumerable(Of Country) = TryCast(source, IEnumerable(Of Country))
If dataSource IsNot Nothing Then
For Each c As Country In dataSource
If c.Name = token Then
Return c.ID.ToString()
End If
Next
End If
Return String.Empty
End Function
The last step we need to do is to replace the default MasterGridViewTemplate with the custom one:
public class CustomGrid : RadGridView
{
protected override RadGridViewElement CreateGridViewElement()
{
return new CustomRadGridViewElement();
}
public override string ThemeClassName
{
get
{
return typeof(RadGridView).FullName;
}
}
}
public class CustomRadGridViewElement : RadGridViewElement
{
protected override MasterGridViewTemplate CreateTemplate()
{
return new CustomMasterGridViewTemplate();
}
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadGridViewElement);
}
}
}
Public Class CustomGrid
Inherits RadGridView
Protected Overrides Function CreateGridViewElement() As RadGridViewElement
Return New CustomRadGridViewElement()
End Function
Public Overrides Property ThemeClassName As String
Get
Return GetType(RadGridView).FullName
End Get
Set(value As String)
MyBase.ThemeClassName = value
End Set
End Property
End Class
Public Class CustomRadGridViewElement
Inherits RadGridViewElement
Protected Overrides Function CreateTemplate() As MasterGridViewTemplate
Return New CustomMasterGridViewTemplate()
End Function
Protected Overrides ReadOnly Property ThemeEffectiveType() As Type
Get
Return GetType(RadGridViewElement)
End Get
End Property
End Class
Clipboard.SetData method gives you the possibility to specify the format of the data to be set. You can customize not only DataFormats.Text, demonstrated above, but DataFormats.CommaSeparatedValue and DataFormats.Html as well, following the same approach.
A complete solution in C# and VB.NET can be found here.