Gridview, TemplateSelectors and Converters

4 posts, 0 answers
  1. Theo
    Theo avatar
    6 posts
    Member since:
    Feb 2013

    Posted 22 Aug 2013 Link to this post

    In our project we want to load settings. Because of the origin of this settings structure these are very generic, exposed via wcf etc. So when we load them in our viewmodel they have the type Object. Also they consist of the real type information so we can convert them to the corresponding type. So far so good. 

    When we load them in a gridview we would like to have different controls, for the different types. A Boolean should be a togglebutton, a int a numeric updown control and a string a regular textbox. For this approach we use Template selectors, but we also need to convert the types of the objects as described above. Therefore we use converters so the controls accepting the correct values and types. Until this point everything works great. We the problem arises when you scroll down in the grid. I guess you did some optimization. Therefore the templates and converters are evaluated when scrolling down. But in a different order then on initial loading. When the grid load for the first time, first the template is selected and then the converter. But when scrolling down, this order changes. To me that's a bit strange, because how can the converter be determined is there is no template. You will find sample code below. Only in our application there are binding errors showing up in the output window, in this example not. But the problem is still the same. Can we work around this issue, or need you guys to update this?

    MainWindow:
    <Grid>
            <Grid.Resources>
                <local:BooleanConverter x:Key="BooleanConverter" />
                <local:InvBooleanConverter x:Key="InvBooleanConverter" />
                <local:StringToIntConverter x:Key="StringToIntConverter" />
                <local:StringToDblConverter x:Key="StringToDblConverter" />
                <local:SettingValueTemplateSelector x:Key="SettingValueTemplateSelector" >
                    <local:SettingValueTemplateSelector.BooleanTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <telerik:RadRadioButton IsChecked="{Binding Path=Value}">
                                    <TextBlock Text="Enabled"/>
                                </telerik:RadRadioButton>
                                <telerik:RadRadioButton IsChecked="{Binding Path=Value}">
                                    <TextBlock Text="Disabled"/>
                                </telerik:RadRadioButton>
                            </StackPanel>
                        </DataTemplate>
                    </local:SettingValueTemplateSelector.BooleanTemplate>
                    <local:SettingValueTemplateSelector.IntTemplate>
                        <DataTemplate>
                            <telerik:RadNumericUpDown Value="{Binding Path=Value, Converter={StaticResource StringToIntConverter}}" NumberDecimalDigits="0"/>
                        </DataTemplate>
                    </local:SettingValueTemplateSelector.IntTemplate>
                    <local:SettingValueTemplateSelector.DoubleTemplate>
                        <DataTemplate>
                            <telerik:RadNumericUpDown Value="{Binding Path=Value,Converter={StaticResource StringToDblConverter}}" />
                        </DataTemplate>
                    </local:SettingValueTemplateSelector.DoubleTemplate>
                    <local:SettingValueTemplateSelector.StringTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Value, Mode=TwoWay}" />
                        </DataTemplate>
                    </local:SettingValueTemplateSelector.StringTemplate>
                </local:SettingValueTemplateSelector>
     
            </Grid.Resources>
            <telerik:RadGridView x:Name="RadGridView" GroupRenderMode="Flat"
                                 RowIndicatorVisibility="Collapsed" CanUserFreezeColumns="False"
                                 ItemsSource="{Binding ElementName=Window1, Path=List}"
                                 IsReadOnly="false"
                                 ScrollMode="Deferred"
                                 AutoExpandGroups="True"
                                 AutoGenerateColumns="false" Margin="0,2,0,-2">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn
                        Header="Value"
                        IsGroupable="True"                   
                        DataMemberBinding="{Binding Value}" 
                        CellTemplateSelector="{StaticResource SettingValueTemplateSelector}"
                        Background="LightGray">
                    </telerik:GridViewDataColumn>
                    <telerik:GridViewDataColumn
                        Header="ValueType"
                        IsGroupable="True"                   
                        DataMemberBinding="{Binding ValueType}"                   
                        Background="LightGray">
                    </telerik:GridViewDataColumn>
                </telerik:RadGridView.Columns>
            </telerik:RadGridView>
        </Grid>
    Template selector:
    public class SettingValueTemplateSelector : DataTemplateSelector
        {
            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
                if (item is DataObjecten)
                {
                    DataObjecten model = item as DataObjecten;
     
                    if (model.ValueType == typeof(int))
                        return this.IntTemplate;
                    else if (model.ValueType == typeof(String))
                        return this.StringTemplate;
                    else if (model.ValueType == typeof(double))
                        return this.DoubleTemplate;
                    else if (model.ValueType == typeof(bool))
                        return this.BooleanTemplate;
                    else
                        return null;
                }
                return null;
            }
    }

    One of the converters (basic):
    public class StringToIntConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int retValue=0;
            if (int.TryParse(value.ToString(), out retValue))
            {
                return retValue;
            }
            else
                return 0;
        }
     
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
              throw new NotSupportedException("Do not use this converter for objects other than boolean");
        }
    }

    Model:
    public class DataObject
      {
          public object Value { get; set; }
          public Type ValueType { get; set; }
      }
     
              List.Add(new DataObject() { Value = "8", ValueType = typeof(int) });
              List.Add(new DataObject() { Value = "8", ValueType = typeof(double) });
              List.Add(new DataObject() { Value = "8gf", ValueType = typeof(string) });
              List.Add(new DataObject() { Value = 454365, ValueType = typeof(int) });
              List.Add(new DataObject() { Value = false, ValueType = typeof(bool) });

  2. Nedyalko Nikolov
    Admin
    Nedyalko Nikolov avatar
    871 posts

    Posted 27 Aug 2013 Link to this post

    Hello,

    I've made a project based on your code snippets and according to me everything works fine on my end.
    Could you please use the attached project as a reference and provide me with more info how to simulate the problem?
    Thank you in advance.

    Regards,
    Nedyalko Nikolov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. Theo
    Theo avatar
    6 posts
    Member since:
    Feb 2013

    Posted 28 Aug 2013 Link to this post

    Thanks for your support. Unfortunately your answer is exactly my problem I am facing at this moment. First of all I changed the data in your project, so debugging would be easier, like so:
    this.DataSource.Add(new DataObject() { Value = 8, ValueType = typeof(int) });
    this.DataSource.Add(new DataObject() { Value = 3d, ValueType = typeof(double) });
    this.DataSource.Add(new DataObject() { Value = "454365j", ValueType = typeof(string) });
    And I copied this several times so the grid has some more data. Start the application and wait until it is loaded. Place breakpoints in the Convert methods of the converters. Now scroll down in the application so data which was not visible now will be. You will notice for example that "454365j" item will be converted to an int. This is because the template selector will hit later. And in this example there is no need for a converter since this is an int. There is were our application also has troubles. The order of execution is not correct in my opinion. 

    btw, should I enter a support ticket for this in the next case?
  4. Nedyalko Nikolov
    Admin
    Nedyalko Nikolov avatar
    871 posts

    Posted 02 Sep 2013 Link to this post

    Hello,

    You could place different controls in each Data template and you will see that there is no problem with bindings. For example I've changed telerik:RadNumericUpDown for doubles with a ordinary TextBlock and TextBlock for string values with TextBox and scrolling work as expected too.
    Could you please send me (in a separate support ticket, because you cannot attach files in a forum post) a repro project which I can debug on my side in order to see what is going on?

    Regards,
    Nedyalko Nikolov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
Back to Top