RadGridView + VirtualQueryableCollectionView + SelectedItem doesn't work

2 posts, 0 answers
  1. Michael
    Michael avatar
    1 posts
    Member since:
    May 2016

    Posted 24 May Link to this post

    Hi,

    I use the RadGridView with a VQCV and dynamic typed data in it. This works fine so far. My problem is, that I want to select the first row after the first set of data was loaded. I get the ItemsLoaded event and set the a SelectedItem property in my ViewModel. This property is bound to the RadGridView but it doesn't render the selected item correct (yellow selection). If I selected rows using the mouse everything works fine, only the programatic selection doesn't work.

    I have debugged the issue for a while and wonder that I can see, that the RadGridView has the correct object referenced by the SelectedItem property, but visually the row is not selected.

    public class MainWindowViewModel : INotifyPropertyChanged
        {
            private DynamicDataRow selectedItem;
     
            public MainWindowViewModel()
            {
                this.Data = new VirtualQueryableCollectionView { LoadSize = 10, VirtualItemCount = 1000 };
                this.Data.ItemsLoading += this.ViewItemsLoading;
                this.Data.ItemsLoaded += this.ViewItemsLoaded;
            }
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            public VirtualQueryableCollectionView Data { get; private set; }
     
            public DynamicDataRow SelectedItem
            {
                get
                {
                    return this.selectedItem;
                }
                set
                {
                    this.selectedItem = value;
                    this.OnPropertyChanged();
                }
            }
     
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                var handler = this.PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
     
            private static void GenerateData(List<dynamic> data, int startIndex = 0)
            {
                var random = new Random(1000);
     
                for (int i = startIndex; i < startIndex + 10; i++)
                {
                    var row = new DynamicDataRow();
     
                    row.Add("Time", DateTime.Now);
                    row.Add("NameD", "Klaus" + i);
                    row.Add("Age", Convert.ToInt16(random.Next(short.MaxValue)));
                    row.Add("Null", (object)null);
                    row.Add("Double", Convert.ToDouble(1.3434));
     
                    data.Add(row);
                }
            }
     
            private void ViewItemsLoaded(object sender, VirtualQueryableCollectionViewItemsLoadedEventArgs e)
            {
                if (e.StartIndex == 10)
                {
                    foreach (DynamicDataRow item in e.Items)
                    {
                        this.SelectedItem = item;
                        break;
                    }
                }
            }
     
            private void ViewItemsLoading(object sender, VirtualQueryableCollectionViewItemsLoadingEventArgs e)
            {
                var source = sender as VirtualQueryableCollectionView;
     
                if (source == null)
                {
                    return;
                }
     
                var data = new List<dynamic>();
                GenerateData(data, e.StartIndex);
                source.Load(e.StartIndex, data);
            }
        }

    /// <summary>
        ///     A collection of dynamic data rows can be used to populate a RadGridView
        ///     with content if the number of columns is variable and only known during
        ///     runtime.
        /// </summary>
        /// <seealso cref="System.Dynamic.DynamicObject" />
        public class DynamicDataRow : DynamicObject
        {
            private readonly IDictionary<string, object> data;
     
            /// <summary>
            ///     Initializes a new instance of the <see cref="DynamicDataRow" /> class.
            /// </summary>
            public DynamicDataRow()
            {
                this.data = new Dictionary<string, object>();
            }
     
            /// <summary>
            ///     Adds a value to a specified column in the current row.
            /// </summary>
            /// <param name="columnName">The column name.</param>
            /// <param name="value">The value for the cell.</param>
            public void Add(string columnName, object value)
            {
                this.data[columnName] = value;
            }
     
            /// <summary>
            ///     Call this method to get a list of all column names. The method
            ///     is used by the RadGridView to generate the columns during runtime-
            /// </summary>
            /// <returns>
            ///     A sequence that contains the column names.
            /// </returns>
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                return this.data.Keys;
            }
     
            /// <summary>
            ///     Provides the implementation for operations that get member values. Classes derived from
            ///     the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method to specify
            ///     dynamic behavior for operations such as getting a value for a property.
            /// </summary>
            /// <param name="binder">
            ///     Provides information about the object that called the dynamic operation.
            ///     The binder.Name property provides the name of the member on which the dynamic operation is
            ///     performed. For example, for the Console.WriteLine(sampleObject.SampleProperty) statement,
            ///     where sampleObject is an instance of the class derived from the
            ///     <see cref="T:System.Dynamic.DynamicObject" /> class, binder.Name returns "SampleProperty".
            ///     The binder.IgnoreCase property specifies whether the member name is case-sensitive.
            /// </param>
            /// <param name="result">
            ///     The result of the get operation. For example, if the method is called
            ///     for a property, you can assign the property value to <paramref name="result" />.
            /// </param>
            /// <returns>
            ///     True if the operation is successful; otherwise, false. If this method returns false, the
            ///     run-time binder of the language determines the behavior. (In most cases, a run-time
            ///     exception is thrown.)
            /// </returns>
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                result = this.data[binder.Name];
                return true;
            }
     
            /// <summary>
            ///     Provides the implementation for operations that set member values. Classes derived
            ///     from the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method
            ///     to specify dynamic behavior for operations such as setting a value for a property.
            /// </summary>
            /// <param name="binder">
            ///     Provides information about the object that called the dynamic
            ///     operation. The binder.Name property provides the name of the member to which the value
            ///     is being assigned. For example, for the statement sampleObject.SampleProperty = "Test",
            ///     where sampleObject is an instance of the class derived from the
            ///     <see cref="T:System.Dynamic.DynamicObject" /> class, binder.Name returns "SampleProperty".
            ///     The binder.IgnoreCase property specifies whether the member name is case-sensitive.
            /// </param>
            /// <param name="value">
            ///     The value to set to the member. For example, for
            ///     sampleObject.SampleProperty = "Test", where sampleObject is an instance of the class
            ///     derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, the
            ///     <paramref name="value" /> is "Test".
            /// </param>
            /// <returns>
            ///     True if the operation is successful; otherwise, false. If this method returns false,
            ///     the run-time binder of the language determines the behavior. (In most cases, a
            ///     language-specific run-time exception is thrown.)
            /// </returns>
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                this.data[binder.Name] = value;
                return true;
            }
        }
    <Window x:Class="WPF.RadGridViewVirtualizing.MainWindow"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
            xmlns:controls="http://schemas.telerik.com/2008/xaml/presentation"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <controls:RadGridView CanUserReorderColumns="False"
                                     ShowGroupPanel="False"
                                     AutoGenerateColumns="True"                                
                                     Grid.Row="0"
                                     IsFilteringAllowed="False"
                                     IsReadOnly="True"
                                     GridLinesVisibility="Both"
                                     SelectionMode="Extended"
                                     SelectionUnit="FullRow"                                
                                     RowIndicatorVisibility="Collapsed"                                
                                     AlternationCount="2"
                                     AlternateRowBackground="#F2F2F2"
                                     ItemsSource="{Binding Data}"
                                     SelectedItem="{Binding SelectedItem}"
                                     CanUserFreezeColumns="False"/>                   
        </Grid>
    </Window>

    I tried to attach a small project which reproduces the problem, but zip was not allowed :(

    Thanks

    Michael

  2. Stefan X1
    Admin
    Stefan X1 avatar
    514 posts

    Posted 27 May Link to this post

    Hello Michael,

    Can you please take a look at the Stop Showing the Unfocused State article, as I assume that the topic discussed in it corresponds to your scenario? As stated in it, you can simply try setting the EnableLostFocusSelectedState property of RadGridView to False.

    Hope this helps.

    Regards,
    Stefan X1
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  3. UI for WPF is Visual Studio 2017 Ready
Back to Top