This is a migrated thread and some comments may be shown as answers.

GridViewDataColumn behavior weird when using image and text both in one column.

3 Answers 114 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Sourabh
Top achievements
Rank 1
Sourabh asked on 11 Jun 2012, 12:15 PM
I have created a GridView using SharePoint data. Data is coming from SharePoint service. Grid generate columns based upon the SharePoint view. Now I have two columns other than normal columns is such a type, that it's display image as well as text under the image.

The first column partly fit into the webpart screen, and the second column visible when I scroll horizontally.

You can see the images for first two columns (first.png, and second.png)

Now the problem occurs when I scroll back to the original position the data of the first column swap to the data of the second column.

I am using the license production version of gridview control 2011.3.1116.1040

Here my code goes:

in the .cs file setupGrid method:


bind =new Binding(bindingName); //bindingName="Operation";                       
                        datacolumn = new GridViewDataColumn() { Header = headerWithToolTip, DataMemberBinding = bind };                        
                        datacolumn.CellTemplate = (DataTemplate)Resources["StatusTemplate"];


filling the datasource:

 foreach (var item in _statusAndDescriptionColumn) //_statusAndDescriptionColumn is List<string> of columns

                    {
                        IEnumerable<XElement> statusField = _fields.Where(i => i.Attribute("DisplayName").Value == item.Split(";".ToArray(), StringSplitOptions.RemoveEmptyEntries)[0]);
                        string statusLongName = statusField.ElementAt(0).Attribute("Name").Value;
                        string statusBindingName = CleanStringForBinding(statusLongName);                                                
                        string statusdisplayName = CleanSharePointString(statusField.ElementAt(0).Attribute("DisplayName").Value);                       
                        StatusAndDescription st = new StatusAndDescription();
                        if (element.Attribute(statusLongName) != null && element.Attribute(statusLongName).Value != string.Empty)
                        {
                            foreach (var sdItem in _statusAndDescriptionList)
                            {
                                if (sdItem.StatusColumn == statusdisplayName && sdItem.StatusDefnition == element.Attribute(statusLongName).Value)
                                {                                    
                                    st = sdItem;
                                    break;
                                }
                            }
                        }
                            
                        if (item.Split(";".ToArray(), StringSplitOptions.RemoveEmptyEntries).Count() == 2)
                        {
                            IEnumerable<XElement> descField = _fields.Where(i => i.Attribute("DisplayName").Value == item.Split(";".ToArray(), StringSplitOptions.RemoveEmptyEntries)[1]);
                            string descLongName = descField.ElementAt(0).Attribute("Name").Value;                            
                            st.StatusDescription = element.Attribute(descLongName).Value;
                        }
                        dic.Add(statusBindingName, ConvertToType("Status", element.Attribute(statusLongName).Value));
                    }

data.Add(dic); // data is ObservableCollection<IDictionary>
IEnumerable dataSource = data.ToDataSource();
        DataGrid.ItemsSource = dataSource;
* ToDataSource is static method, at the end you can find the code for that:

in the .xaml file:

<DataTemplate x:Key="StatusTemplate">
            <ContentControl Loaded="ContentControl_Loaded_Status"/>
        </DataTemplate>


back in .cs file:

private void ContentControl_Loaded_Status(object sender, RoutedEventArgs e)
        {
            var contentControl = (ContentControl)sender;
            var v = (GridViewCell)(contentControl).Parent;
            if (v == null) return;
            string value = v.Value.ToString();
            if (string.IsNullOrEmpty(value)) return;
            StackPanel stackP = new StackPanel() { HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch };
            string idString = string.Empty;
            string headetText = ((((ContentControl)sender).Parent as GridViewCell).Column.Header as TextBlock).Text;
            var x = (((ContentControl)sender).Parent as GridViewCell).ParentRow.Item;
            foreach (var item in _statusAndDescriptionColumn)
            {
                if(item.Contains(headetText))
                {
                    idString = (x.GetType().GetProperty(item.Split(";".ToArray())[1]) as PropertyInfo).GetValue(x, null) as string;
                    break;
                }
            }


            StatusAndDescription st = _statusAndDescriptionList.SingleOrDefault(i=> i.StatusColumn == headetText && i.StatusDefnition == value);
            if (st == null) return;
            
                if (st.StatusIconOrColor.Contains("/"))
                {
                    Uri uri = new Uri(st.StatusIconOrColor, UriKind.RelativeOrAbsolute);
                    ImageSource source = new BitmapImage(uri);
                    Image img = new Image() {Height = 13, Width=13, HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, Margin = new Thickness(2), Source = source};
                    if (!string.IsNullOrEmpty(st.StatusDefnition))
                    {
                        System.Windows.Controls.ToolTip toolTip = new System.Windows.Controls.ToolTip() { HorizontalOffset = 10, VerticalOffset = 10, Content = st.StatusDefnition };
                        ToolTipService.SetToolTip(img, toolTip);
                    }
                    stackP.Children.Add(img);
                }
                else
                {
                        Ellipse circle = new Ellipse();
                        circle.Width = 13;
                        circle.Height = 13;
                        circle.Margin = new Thickness(4);
                        circle.Fill = new SolidColorBrush(st.StatusIconOrColor.ToColor().Value);
                        circle.StrokeThickness = 1;
                        circle.Stroke = new SolidColorBrush(Colors.Black);
                        stackP.Children.Add(circle);
                        circle.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                        if (!string.IsNullOrEmpty(st.StatusDefnition))
                        {
                            System.Windows.Controls.ToolTip toolTip = new System.Windows.Controls.ToolTip() { HorizontalOffset = 10, VerticalOffset = 10, Content = st.StatusDefnition };
                            ToolTipService.SetToolTip(circle, toolTip);
                        }
                }
                if (!string.IsNullOrEmpty(st.StatusDescription))
                {
                    MWH.WebParts.Common.HtmlRichTextBox descText = new MWH.WebParts.Common.HtmlRichTextBox() { TextWrapping = TextWrapping.Wrap, Background = new SolidColorBrush(Colors.Transparent), BorderThickness = new Thickness(0), BorderBrush = new SolidColorBrush(Colors.Transparent) };
                    descText.IsReadOnly = true;
                    descText.Load(st.StatusDescription);
                    stackP.Children.Add(descText);
                }
           
            contentControl.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            contentControl.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;
            contentControl.Content = stackP;
        }


Static datasourcecreator:


using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Collections;
using System.Reflection.Emit;
using System.Reflection;
using System.Text;


namespace MWH.WebParts.TreeListWebPart
{
    public static class DataSourceCreator
    {
        private static readonly Regex PropertNameRegex =
                new Regex(@"^[A-Za-z]+[A-Za-z0-9_]*$", RegexOptions.Singleline);


        private static readonly Dictionary<string, Type> _typeBySigniture = new Dictionary<string, Type>();


        public static IEnumerable ToDataSource(this IEnumerable<IDictionary> list)
        {
            IDictionary firstDict = null;
            bool hasData = false;
            foreach (IDictionary currentDict in list)
            {
                hasData = true;
                firstDict = currentDict;
                break;
            }
            if (!hasData)
            {
                return new object[] { };
            }
            if (firstDict == null)
            {
                throw new ArgumentException("IDictionary entry cannot be null");
            }


            string typeSigniture = GetTypeSigniture(firstDict);


            Type objectType = GetTypeByTypeSigniture(typeSigniture);


            if (objectType == null)
            {
                TypeBuilder tb = GetTypeBuilder(typeSigniture);


                ConstructorBuilder constructor =
                            tb.DefineDefaultConstructor(
                                        MethodAttributes.Public |
                                        MethodAttributes.SpecialName |
                                        MethodAttributes.RTSpecialName);




                foreach (DictionaryEntry pair in firstDict)
                {
                    if (PropertNameRegex.IsMatch(Convert.ToString(pair.Key), 0))
                    {
                        CreateProperty(tb,
                                        Convert.ToString(pair.Key),
                                        GetValueType(pair.Value));
                    }
                    else
                    {
                        throw new ArgumentException(
                                    @"Each key of IDictionary must be 
                                alphanumeric and start with character.");
                    }
                }
                objectType = tb.CreateType();


                _typeBySigniture.Add(typeSigniture, objectType);
            }


            return GenerateEnumerable(objectType, list, firstDict);
        }


        private static Type GetTypeByTypeSigniture(string typeSigniture)
        {
            Type type;
            return _typeBySigniture.TryGetValue(typeSigniture, out type) ? type : null;
        }


        private static Type GetValueType(object value)
        {
            return value == null ? typeof(object) : value.GetType();
        }


        private static string GetTypeSigniture(IDictionary firstDict)
        {
            StringBuilder sb = new StringBuilder();
            foreach (DictionaryEntry pair in firstDict)
            {
                sb.AppendFormat("_{0}_{1}", pair.Key, GetValueType(pair.Value));
            }
            return sb.ToString().GetHashCode().ToString().Replace("-", "Minus");
        }


        private static IEnumerable GenerateEnumerable(
                 Type objectType, IEnumerable<IDictionary> list, IDictionary firstDict)
        {
            var listType = typeof(List<>).MakeGenericType(new[] { objectType });
            var listOfCustom = Activator.CreateInstance(listType);


            foreach (var currentDict in list)
            {
                if (currentDict == null)
                {
                    throw new ArgumentException("IDictionary entry cannot be null");
                }
                var row = Activator.CreateInstance(objectType);
                foreach (DictionaryEntry pair in firstDict)
                {
                    if (currentDict.Contains(pair.Key))
                    {
                        PropertyInfo property =
                            objectType.GetProperty(Convert.ToString(pair.Key));
                        property.SetValue(
                            row,
                            Convert.ChangeType(
                                    currentDict[pair.Key],
                                    property.PropertyType,
                                    null),
                            null);
                    }
                }
                listType.GetMethod("Add").Invoke(listOfCustom, new[] { row });
            }
            return listOfCustom as IEnumerable;
        }


        private static TypeBuilder GetTypeBuilder(string typeSigniture)
        {
            AssemblyName an = new AssemblyName("TempAssembly" + typeSigniture);
            AssemblyBuilder assemblyBuilder =
                AppDomain.CurrentDomain.DefineDynamicAssembly(
                    an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");


            TypeBuilder tb = moduleBuilder.DefineType("TempType" + typeSigniture
                                , TypeAttributes.Public |
                                TypeAttributes.Class |
                                TypeAttributes.AutoClass |
                                TypeAttributes.AnsiClass |
                                TypeAttributes.BeforeFieldInit |
                                TypeAttributes.AutoLayout
                                , typeof(object));
            return tb;
        }


        private static void CreateProperty(
                        TypeBuilder tb, string propertyName, Type propertyType)
        {
            FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName,
                                                        propertyType,
                                                        FieldAttributes.Private);




            PropertyBuilder propertyBuilder =
                tb.DefineProperty(
                    propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder getPropMthdBldr =
                tb.DefineMethod("get_" + propertyName,
                    MethodAttributes.Public |
                    MethodAttributes.SpecialName |
                    MethodAttributes.HideBySig,
                    propertyType, Type.EmptyTypes);


            ILGenerator getIL = getPropMthdBldr.GetILGenerator();


            getIL.Emit(OpCodes.Ldarg_0);
            getIL.Emit(OpCodes.Ldfld, fieldBuilder);
            getIL.Emit(OpCodes.Ret);


            MethodBuilder setPropMthdBldr =
                tb.DefineMethod("set_" + propertyName,
                  MethodAttributes.Public |
                  MethodAttributes.SpecialName |
                  MethodAttributes.HideBySig,
                  null, new Type[] { propertyType });


            ILGenerator setIL = setPropMthdBldr.GetILGenerator();


            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldarg_1);
            setIL.Emit(OpCodes.Stfld, fieldBuilder);
            setIL.Emit(OpCodes.Ret);


            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }
}



3 Answers, 1 is accepted

Sort by
0
James
Top achievements
Rank 1
answered on 14 Jun 2012, 09:31 AM
can you please look into the issue, i need that issue to be fixed. 
0
Dimitrina
Telerik team
answered on 14 Jun 2012, 10:19 AM
Hello,

 Having the code you have posted we may not tell what exactly caused such a behaviour. Usually the reason for it would be that you work with visual elements (i.e. GridViewCell) and their properties. For performance reasons the RadGridView uses virtualization when scrolling . This means that the cells and rows are being reused, they are added and removed to/from  the visual tree dynamically

You can define the Image and the Text directly in the CellTemplate of the GridViewDataColumn and populate their content using binding. Please check this help article for a reference.

Regards,
Didie
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Sourabh
Top achievements
Rank 1
answered on 15 Jun 2012, 05:43 AM
hi Didie,

we don't have fixed column to show in the grid view, we are generating column dynamically. On the basis of column type, we are setting the data template of the column.

so the code goes for generating dynamic column is 

foreach (XElement field in _fields)
{
string longName = field.Attribute("Name").Value;
string bindingName = CleanStringForBinding(longName);
string type = field.Attribute("Type").Value;
bind =new Binding(bindingName); //bindingName="Operation";  

if(type=="Status")
{
datacolumn = new GridViewDataColumn() { Header = headerWithToolTip, DataMemberBinding = bind }; 
datacolumn.CellTemplate = (DataTemplate)Resources["StatusTemplate"]; 
}
else
{
datacolumn = new GridViewDataColumn(){ Header= headerWithToolTip, DataMemberBinding = bind  };
}
 

in .xaml;
<DataTemplate x:Key="StatusTemplate">             <ContentControl Loaded="ContentControl_Loaded_Status"/> </DataTemplate>

hope you understand the situation now.

Regards,
Sourabh Bose
Tags
GridView
Asked by
Sourabh
Top achievements
Rank 1
Answers by
James
Top achievements
Rank 1
Dimitrina
Telerik team
Sourabh
Top achievements
Rank 1
Share this question
or