GridView column virtualization causing binding errors

2 posts, 0 answers
  1. Dave
    Dave avatar
    1 posts
    Member since:
    Feb 2017

    Posted 02 Oct Link to this post

    Hello,

    Using components from UI for WPF R2 2017 ... It appears that RadGridView column virtualization is causing some binding errors, which in turn seem to place the GridView in a state where column header bindings fail when those columns are not rendered initially due to virtualization.  For example, the sample below works if EnableColumnVirtualization is set to false, or if the window size is large enough such that all columns are rendered (such as 800 in the example below).

    With the Office2016 theme, I'm getting two types of binding errors:
    System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Telerik.Windows.Controls.RadGridView', AncestorLevel='1''. BindingExpression:Path=DataContext.HeaderText; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
    System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Telerik.Windows.Controls.GridView.DataCellsPresenter', AncestorLevel='1''. BindingExpression:Path=Foreground; DataItem=null; target element is 'ContentControl' (Name='PART_ContentPresenter'); target property is 'Foreground' (type 'Brush')

    (The sample has a single row in the ItemsSource ... real world situations would produce dozens+ of the errors looking for DataCellsPresenter.)

    Other themes I've tested just produce the first binding error.

    Here's the .xaml:

    <Window x:Class="TelerikWpfApp.MainWindow"
        Title="MainWindow" Height="300" Width="400">
      <Grid>
        <telerik:RadGridView EnableColumnVirtualization="True"
            AutoGenerateColumns="False"
            GroupRenderMode="Flat"
            ItemsSource="{Binding TestObjects}">
          <telerik:RadGridView.Columns>
              <telerik:GridViewDataColumn Header="Name" DataMemberBinding="{Binding Name}"/>
              <telerik:GridViewDataColumn Header="Column 1 Name" DataMemberBinding="{Binding Column1}"/>
              <telerik:GridViewDataColumn Header="Column 2 Name" DataMemberBinding="{Binding Column1}"/>
              <telerik:GridViewDataColumn Header="Column 3 Name" DataMemberBinding="{Binding Column1}"/>
              <telerik:GridViewDataColumn Header="Column 4 Name" DataMemberBinding="{Binding Column1}"/>
              <telerik:GridViewDataColumn Header="Column 5 Name" DataMemberBinding="{Binding Column1}"/>
              <telerik:GridViewDataColumn Header="Column 6 Name" DataMemberBinding="{Binding Column1}"/>
                     
              <telerik:GridViewDataColumn DataMemberBinding="{Binding Column1}">
                <telerik:GridViewDataColumn.Header>
                  <TextBlock Text="{Binding DataContext.HeaderText, RelativeSource={RelativeSource AncestorType={x:Type telerik:RadGridView}}}"/>
                </telerik:GridViewDataColumn.Header>
              </telerik:GridViewDataColumn>
          </telerik:RadGridView.Columns>
        </telerik:RadGridView>
      </Grid>
    </Window>

     

    And here's the code:

    using System.Collections.Generic;
    using System.Windows;
    using Telerik.Windows.Controls;
     
    namespace TelerikWpfApp
    {
         public partial class MainWindow : Window
        {
            public class TestObject
            {
                public string Name { get; set; }
                public string Column1 { get; set; }
            }
     
            public MainWindow()
            {
                StyleManager.ApplicationTheme = new Office2016Theme();
     
                InitializeComponent();
     
                this.DataContext = this;
     
                TestObjects = new List<TestObject>
                {
                    new TestObject { Name = "1", Column1 = "Column1" }
                };
            }
     
            public List<TestObject> TestObjects { get; set; }
     
            public string HeaderText { get { return "Test"; } }
        }
    }

     

    Any assistance would be appreciated.

  2. Dilyan Traykov
    Admin
    Dilyan Traykov avatar
    603 posts

    Posted 04 Oct Link to this post

    Hello Dave,

    The reason for this binding error has been explained in the following thread.

    "[RadGridView] is creating some cell elements in advance, that are not yet attached to the visual tree. Since the cell element is not yet part of the visual tree, ancestor relation bending fails."

    To overcome this and avoid a cyclic dependency, you can use the approach suggested in this thread.

    Here's the modified code that resolves the errors at my end:

    <telerik:RadGridView EnableColumnVirtualization="True"
    AutoGenerateColumns="False"
    GroupRenderMode="Flat"
    ItemsSource="{Binding TestObjects}">
        <telerik:RadGridView.Resources>
            <DiscreteObjectKeyFrame x:Key="proxy" Value="{Binding}"/>
        </telerik:RadGridView.Resources>
        <telerik:RadGridView.Columns>
            <telerik:GridViewDataColumn Header="Name" DataMemberBinding="{Binding Name}"/>
            <telerik:GridViewDataColumn Header="Column 1 Name" DataMemberBinding="{Binding Column1}"/>
            <telerik:GridViewDataColumn Header="Column 2 Name" DataMemberBinding="{Binding Column1}"/>
            <telerik:GridViewDataColumn Header="Column 3 Name" DataMemberBinding="{Binding Column1}"/>
            <telerik:GridViewDataColumn Header="Column 4 Name" DataMemberBinding="{Binding Column1}"/>
            <telerik:GridViewDataColumn Header="Column 5 Name" DataMemberBinding="{Binding Column1}"/>
            <telerik:GridViewDataColumn Header="Column 6 Name" DataMemberBinding="{Binding Column1}"/>
     
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Column1}">
                <telerik:GridViewDataColumn.Header>
                    <TextBlock Text="{Binding Path=Value.DataContext.HeaderText, Source={StaticResource proxy}}"/>
                </telerik:GridViewDataColumn.Header>
            </telerik:GridViewDataColumn>
        </telerik:RadGridView.Columns>
    </telerik:RadGridView>

    Please let me know if this works for you.

    Regards,
    Dilyan Traykov
    Progress Telerik
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Back to Top