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

Why are Details rows in Master/Detail hierarchical RadGridView not displayed?

7 Answers 157 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Dmitry
Top achievements
Rank 1
Dmitry asked on 06 Feb 2017, 08:55 AM

Hellow.

I do Master/Detail hierarchical RadGridView in the following manner. The View is:

<UserControl x:Class="RecordAndPlaybackSession.Views.RecordAndPlaybackSessionView"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             xmlns:prism="http://prismlibrary.com/"
             xmlns:commonControls="clr-namespace:CommonWpfControlLibrary;assembly=CommonWpfControlLibrary"
             prism:ViewModelLocator.AutoWireViewModel="True">
 
    <i:Interaction.Triggers>
        <!--<OK> dialog-->
        <prism:InteractionRequestTrigger SourceObject="{Binding NotificationRequest, Mode=OneWay}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <commonControls:NotificationDialogPopupView/>
                </prism:PopupWindowAction.WindowContent>
                <prism:PopupWindowAction.WindowStyle>
                    <Style TargetType="Window">
                        <Setter Property="ResizeMode" Value="NoResize"/>
                        <Setter Property="SizeToContent" Value="WidthAndHeight"/>
                    </Style>
                </prism:PopupWindowAction.WindowStyle>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers>
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="35" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
         
        <Grid.Resources>
            <DataTemplate x:Key="RowDetailsTemplate">
                <telerik:RadGridView Name="SavedSesionsGrid" IsReadOnly="True" ItemsSource="{Binding SavedWorkingSesions}" AutoGenerateColumns="False" ShowGroupPanel="False">
                    <telerik:RadGridView.Columns>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Date}" Header="Session date"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_Begin}" Header="Time Begin"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_End}" Header="Time End"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Modbus_Transmision_Mode}" Header="MODBUS Transmision Mode"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Brief_Description}" Header="Brief Description" IsReadOnly="False"/>
                    </telerik:RadGridView.Columns>
                </telerik:RadGridView>
            </DataTemplate>
        </Grid.Resources>
         
        <telerik:RadGridView Grid.Row="0" Grid.Column="0" Name="DevicesGrid" ItemsSource="{Binding DevicesWithSavedSesions}" AutoGenerateColumns="False"
                             IsReadOnly="True" CanUserDeleteRows="False" CanUserFreezeColumns="False" CanUserInsertRows="False" CanUserReorderColumns="False"
                             CanUserResizeRows="False" CanUserSearch="False" CanUserSortColumns="False" IsFilteringAllowed="False" SelectedItem="{Binding SelectedDevice}"
                             RowIndicatorVisibility="Collapsed" RowDetailsTemplate="{StaticResource RowDetailsTemplate}" Margin="5">
            <telerik:RadGridView.Columns>
                <telerik:GridViewToggleRowDetailsColumn/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding DisplayedName}" Header="Name"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SerialNumber}" Header="Serial #/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedBeamsQuantity}" Header="Beams Quantity"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedInnerDiameter}" Header="Inner Diameter"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding CompanyOwnerOfDevice}" Header="Device Owner"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding MountingLocation}" Header="Locality"/>
                <telerik:GridViewCheckBoxColumn DataMemberBinding="{Binding IsCurrentlyConnected}" Header="Is Connected">
                    <telerik:GridViewCheckBoxColumn.CellStyle>
                        <Style TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
                            <Setter Property="HorizontalContentAlignment" Value="Center" />
                        </Style>
                    </telerik:GridViewCheckBoxColumn.CellStyle>
                </telerik:GridViewCheckBoxColumn>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
        <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
            <telerik:RadButton Height="25" Width="100" Margin="0 0 0 5" Content="Save" ToolTip="Save current sesion."
                               Command="{Binding SaveWorkingSessionCommand}"/>
            <telerik:RadButton Height="25" Width="100" Margin="10 0 10 5" Content="Stop" ToolTip="Stop saving process of current sesion"
                               Command="{Binding StopSavingOfWorkingSesionCommand}"/>
            <telerik:RadButton Height="25" Width="100" Margin="10 0 10 5" Content="Play" ToolTip="Play selected saving sesion"
                               Command="{Binding PlaySavedSessionCommand}"/>
            <telerik:RadButton Height="25" Width="100" Margin="0 0 0 5" Content="Delete" ToolTip="Delete selected saving session"
                               Command="{Binding DeleteSavedSessionCommand}"/>
        </StackPanel>
    </Grid>
</UserControl>

In the ViewModel I create (in particular) the folowing property that is bound to SelectedItem of master RadGridView. This is the user-selected device which session must be saved. Please see it below:

#region Properties
. . . . . . . . .      
public object SelectedDevice
{
     get { return this._selectedDevice; }
     set
     {
          if (this.SetProperty(ref this._selectedDevice, value))
          this.SaveWorkingSessionCommand.RaiseCanExecuteChanged();
     }
}
. . . . . . . . . . . . .
#endregion

And also the following properties:

#region Properties
 . . . . . . . . . . .
 /// <summary>
 /// Gets or sets the collection of devices that have saving sessions, and currently conected device.
 /// </summary>
 public ObservableCollection<Device> DevicesWithSavedSesions
 {
     get { return this._devicesWithSavedSessions; }
     set { this._devicesWithSavedSessions = value; }
 }
 
 /// <summary>
 /// Gets or sets the collection of saved working sessions per device.
 /// </summary>
 ObservableCollection<DeviceWorkingSession> SavedWorkingSesions
 {
     get
     {
         return this._savedWorkingSesions;//new ObservableCollection<DeviceWorkingSession>(this.DevicesWithSavedSesions.SelectMany(device => device.SavedWorkingSession));
     }
     set { this.SetProperty(ref this._savedWorkingSesions, value); }
 }
 . . . . . . . . . . .
 #endregion

I initialize these properties in constructor of ViewModel:

this.DevicesWithSavedSesions = new RadObservableCollection<Device>();
this.SavedWorkingSesions = new RadObservableCollection<DeviceWorkingSession>();

And in 'SaveWorkingSesionCommand' I do the following:

// Create instance of record with information about session being saved.
DeviceWorkingSession savedSession = new DeviceWorkingSession();
// GUID of saved sesion.
savedSession.Id = Guid.NewGuid();
// Id of device which sesion is saved.
savedSession.Devices_Id = GlobalStaticMembers.SharedProfileHeader.Id;
// Date of saving of the session.
DateTime sessionDateTime = DateTime.Now;
savedSession.Date = sessionDateTime.Date;
// Time when sesion saving begins
savedSession.Time_Begin = sessionDateTime.TimeOfDay;
savedSession.StrTimeBegin = savedSession.Time_Begin.ToString(@"hh\:mm\:ss\:fff");
// Transmision mode of MODBUS protocol.
savedSession.Modbus_Transmision_Mode = GlobalStaticMembers.ModbusTransmisionMode;
// Save session in 'Device' instance (in the manner as it done in your 'ExpandAllRowsDetails' example in your SDK).
(this.SelectedDevice as Device).SavedWorkingSession.Add(savedSession);
// Save session in collection that is binding source.
this.SavedWorkingSesions.Add(savedSession);

Below is the definition of SavedWorkingSession from Device class:

public ObservableCollection<DeviceWorkingSession> SavedWorkingSession
{
    get
    {
        if (this._savedWorkingSession == null)
           this._savedWorkingSession = new ObservableCollection<DeviceWorkingSession>();
        return this._savedWorkingSession;
    }
}

But I can not see detail records. Please see 'HierarchyMasterDetail.PNG' file attached. If you need more detail, please write me.

7 Answers, 1 is accepted

Sort by
0
Dmitry
Top achievements
Rank 1
answered on 06 Feb 2017, 10:28 AM

Note! 'SavedWorkingSesions' property in ViewModel is public!

public ObservableCollection<DeviceWorkingSession> SavedWorkingSesions
{
    get
    {
        return this._savedWorkingSesions;//new ObservableCollection<DeviceWorkingSession>(this.DevicesWithSavedSesions.SelectMany(device => device.SavedWorkingSession));
    }
    set { this.SetProperty(ref this._savedWorkingSesions, value); }
}
0
Stefan Nenchev
Telerik team
answered on 08 Feb 2017, 04:04 PM
Hello Yaroslav,

Do you see any binding errors in the Output Window? Generally, the ItemsSource of the Inner RadGridView should point to a collection property of your main object(the Device). Does your Device object expose a SavedWorkingSessions property? 
If not, have in mind that the DataContext of the inner RadGridView is the respective item of the parent RadGridView. With this in mind, you might need to explicitly point the Source for the ItemsSource collection of the inner grid.

Regards,
Stefan Nenchev
Telerik by Progress
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 you to write beautiful native mobile apps using a single shared C# codebase.
0
Dmitry
Top achievements
Rank 1
answered on 09 Feb 2017, 05:18 AM

Hello, Stefan. Thank you very much for your help and support. You've ansvered me: "Does your Device object expose a SavedWorkingSessions property?". So below I display you 'Device' class definition (I bag your pardon for Russian comments).

public class Device : ProfileElementType, INotifyPropertyChanged
{
    #region Поля
 
    /// <summary>
    /// Уникальный идентификатор для записи в БД SQL Server.
    /// </summary>
    private Guid _id;
    /// <summary>
    /// Числовой код типа устройства.
    /// </summary>
    private ushort _deviceTypeCode;
    /// <summary>
    /// Краткое описание функциональной принадлежности прибора. (Например, "Расходомер газа".)
    /// </summary>
    private string _name;
    /// <summary>
    /// Марка прибора. (Например, "РГ-1".)
    /// </summary>
    private string _brand;
    /// <summary>
    /// Наименование прибора, отображаемое на экране, состоящее из краткого описания
    /// его функциональной принадлежности и марки. (Например, "Расходомер газа РГ-1".)
    /// </summary>
    private string _displayedName;
    /// <summary>
    /// Серийный номер прибора. (Например, 08348541).
    /// </summary>
    private string _serialNumber;
    /// <summary>
    /// Имя файла c расширением .DAT, в который будет выполняться сериализация (сохранение) профиля прибора.
    /// </summary>
    private string _repositoryFileName;
    /// <summary>
    /// Общее количество регистров в профиле прибора.
    /// </summary>
    private int _registersQuantity;
    /// <summary>
    /// Рабочие сессии этого прибора, которые были сохранены.
    /// </summary>
    private ObservableCollection<DeviceWorkingSession> _savedWorkingSession;
    /// <summary>
    /// Показывает, установлено ли соединение с этим прибором. true - в настоящий момент времени программа
    /// подсоединена к этому прибору, false - нет.
    /// </summary>
    private bool _isCurrentlyConnected;
 
    #endregion
 
    #region Конструкторы
    /// <summary>
    /// Создаёт экземпляр класса Device.
    /// </summary>
    public Device()
    {
        this.ElementType = this.GetType();
        this.ElementTypeName = this.ElementType.Name;
        this.Id = Guid.NewGuid();
        this.Name = "Расходомер";
        this.Brand = "РГ";
        this.SerialNumber = "0";
        this.DisplayedName = string.Concat(this._name, " ", this._brand);
        this.RegistersQuantity = 0;
    }
 
    /// <summary>
    /// Создаёт экземпляр класса Device на основе другого экземпляра этого же класса.
    /// </summary>
    /// <param name="device"></param>
    public Device(Device device)
    {
        try
        {
            this.ElementType = this.GetType();
            this.ElementTypeName = this.ElementType.Name;
            this.Id = device.Id;
            this.DeviceTypeCode = device.DeviceTypeCode;
            this.Name = string.Copy(device.Name);
            this.Brand = string.Copy(device.Brand);
            this.DisplayedName = string.Copy(device.DisplayedName);
            this.RepositoryFileName = string.Copy(device.RepositoryFileName);
            if (device.SerialNumber != null && device.SerialNumber != string.Empty)
                this.SerialNumber = string.Copy(device.SerialNumber);
            this.RegistersQuantity = device.RegistersQuantity;
        }
        catch (NullReferenceException ex)
        {
            throw new NullReferenceException("Ошибка: " + ex.HResult.ToString() + ". Экземпляр Device, переданный конструктору в качестве аргумента, имеет значение null");
        }
    }
    #endregion
 
    #region INotifyPropertyChanged implementation
 
    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        GlobalStaticMembers.F_ProfileChanging = true;
    }
 
    #endregion
 
    #region Свойства
 
    /// <summary>
    /// Возвращает или задаёт уникальный идентификатор для записи о профиле прибора в БД SQL Server.
    /// </summary>
    public Guid Id
    {
        get { return this._id; }
        set
        {
            if (value != this._id)
                this._id = value;
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт числовой код типа устройства.
    /// </summary>
    [Display(Description = "Числовой код, обозначающий тип устройства.", Name = "Тип прибора")]
    public ushort DeviceTypeCode
    {
        get { return this._deviceTypeCode; }
        set
        {
            if (value != this._deviceTypeCode)
            {
                this._deviceTypeCode = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт краткое описание функциональной принадлежности прибора.
    /// (Например, "Расходомер газа".)
    /// </summary>
    [Display(Description = "Название прибора согласно его функциональной принадлежности. (Например, \"Расходомер газа\".)", Name = "Название")]
    public string Name
    {
        get { return this._name; }
        set
        {
            if (value != this._name)
            {
                this._name = value;
                NotifyPropertyChanged();
                // Изменить в полном наименовании соответствующую часть.
                if (this.Brand != null && this.Brand != string.Empty)
                    this.DisplayedName = string.Concat(this.Name, " ", this.Brand);
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт марку прибора. (Например, "РГ-1".)
    /// </summary>
    [Display(Description = "Имя марки прибора. (Например, \"РГ - 1\".)", Name = "Марка")]
    public string Brand
    {
        get { return this._brand; }
        set
        {
            if (value != this._brand)
            {
                this._brand = value;
                NotifyPropertyChanged();
                // Изменить в полном наименовании соответствующую часть.
                if (this.Name != null && this.Name != string.Empty)
                    this.DisplayedName = string.Concat(this.Name, " ", this.Brand);
                // Определить (или переопределить) имя для файла с расширением .DAT, в который будет сохранён профиль прибора.
                string currentDate = (DateTime.Now.ToShortDateString()).Replace(".", null);
                string currentTime = (DateTime.Now.ToLongTimeString()).Replace(":", null);
                this.RepositoryFileName = this.Brand + "_" + currentDate + currentTime + "_" + (this.Id.ToString()).Replace("-", null) + ".dat";
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт полное наименование прибора, отображаемое на экране.
    /// (Например, "Расходомер газа РГ-1".)
    /// </summary>
    [Browsable(false)]
    public string DisplayedName
    {
        get { return this._displayedName; }
        set
        {
            if (value != this._displayedName)
            {
                this._displayedName = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт серийный номер прибора. (Например, 08348541).
    /// </summary>
    [Display(Description = "Серийный номер прибора. (Например, \"08348541\")", Name = "Серийный номер")]
    public string SerialNumber
    {
        get { return this._serialNumber; }
        set
        {
            if (value != this._serialNumber)
            {
                this._serialNumber = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт имя файла c расширением .DAT, в который будет выполняться сериализация (сохранение) профиля прибора.
    /// </summary>
    [Browsable(false)]
    public string RepositoryFileName
    {
        get { return this._repositoryFileName; }
        set
        {
            if (value != this._repositoryFileName)
            {
                this._repositoryFileName = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт общее количество регистров в профиле прибора.
    /// </summary>
    [Browsable(false)]
    public int RegistersQuantity
    {
        get { return this._registersQuantity; }
        set
        {
            if (value != this._registersQuantity)
            {
                this._registersQuantity = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт рабочие сессии этого прибора, которые были сохранены.
    /// </summary>
    public ObservableCollection<DeviceWorkingSession> SavedWorkingSession
    {
        get
        {
            if (this._savedWorkingSession == null)
                this._savedWorkingSession = new ObservableCollection<DeviceWorkingSession>();
            return this._savedWorkingSession;
        }
    }
 
    /// <summary>
    /// Возвращает или задаёт значение, показывающее, установлено ли соединение с этим прибором.
    /// true - в настоящий момент времени программа подсоединена к этому прибору, false - нет.
    /// </summary>
    public bool IsCurrentlyConnected
    {
        get { return this._isCurrentlyConnected; }
        set
        {
            if(value!=this._isCurrentlyConnected)
            {
                this._isCurrentlyConnected = value;
                NotifyPropertyChanged();
            }
        }
    }
 
    /// <summary>
    /// Название места установки.
    /// </summary>
    public string MountingLocation { get; set; }
    
    /// <summary>
    /// Компания-собственник прибора (расходомера или датчика).
    /// </summary>
    public string CompanyOwnerOfDevice { get; set; }
 
    /// <summary>
    /// Адрес компаниии, использующей прибор - улица, дом.
    /// </summary>
    public string StreetHouseAddress { get; set; }
 
    /// <summary>
    /// Адрес компании-собственника - населённый пункт.
    /// </summary>
    public string InhabitedLocality { get; set; }
 
    /// <summary>
    ///  Адрес компании-собственника - область.
    /// </summary>
    public string Region { get; set; }
 
    /// <summary>
    /// Адрес компании-собственника - страна.
    /// </summary>
    public string Country { get; set; }
 
    /// <summary>
    /// Почтовый индекс компании-собственника согласно указанному адресу.
    /// </summary>
    public string ZipCode { get; set; }
    /// <summary>
    /// Версия программного и аппаратного обеспечения прибора (расходомера или датччика).
    /// </summary>
    public string SwHwVersion { get; set; }
    /// <summary>
    /// Тип прибора (расходомера или датчика) cогласно его классу взрывозащиты.
    /// </summary>
    public string DeviceType { get; set; }
 
    /// <summary>
    /// Счётчик/Сантиметр - внутренний диаметр канала для прохождения измеряемого потока у прибора.
    /// </summary>
    public string SelectedInnerDiameter { get; set; }
 
    /// <summary>
    /// Выбранное количество измерительных ультразвуковых лучей.
    /// </summary>
    public string SelectedBeamsQuantity { get; set; }
 
    /// <summary>
    /// Выбранный класс взрывозащиты прибора (расходомера или датчика).
    /// </summary>
    public string SelectedExClass { get; set; }
 
    /// <summary>
    /// Путь к папке, в которой сохраняется информация по состоянию
    /// лучей, отчётов и записей.
    /// </summary>
    public string PathToStorage { get; set; }
 
    #endregion
}

Below I display Master/Detail XAML snippet with some corrections.

<Grid.Resources>
    <DataTemplate x:Key="RowDetailsTemplate">
        <telerik:RadGridView Name="SavedSesionsGrid" IsReadOnly="True" ItemsSource="{Binding SavedWorkingSesions}" AutoGenerateColumns="False" ShowGroupPanel="False"
                             SelectedItem="{Binding SelectedSavedSesion}">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Date}" Header="Дата сессии"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_Begin}" Header="Время начала"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_End}" Header="Время окончания"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Modbus_Transmision_Mode}" Header="Режим передачи MODBUS"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Brief_Description}" Header="Краткое описание" IsReadOnly="False"/>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
    </DataTemplate>
</Grid.Resources>
 
<telerik:RadGridView Grid.Row="0" Grid.Column="0" Name="DevicesGrid" ItemsSource="{Binding DevicesWithSavedSesions}" AutoGenerateColumns="False"
                     IsReadOnly="True" CanUserDeleteRows="False" CanUserFreezeColumns="False" CanUserInsertRows="False" CanUserReorderColumns="False"
                     CanUserResizeRows="False" CanUserSearch="False" CanUserSortColumns="False" IsFilteringAllowed="False" SelectedItem="{Binding SelectedDevice}"
                     RowDetailsTemplate="{StaticResource RowDetailsTemplate}" Margin="5">
    <telerik:RadGridView.Columns>
        <telerik:GridViewToggleRowDetailsColumn/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding DisplayedName}" Header="Наименование"/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding SerialNumber}" Header="Серийный №"/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedBeamsQuantity}" Header="Количество лучей"/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedInnerDiameter}" Header="Внутренний диаметр"/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding CompanyOwnerOfDevice}" Header="Владелец прибора"/>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding MountingLocation}" Header="Место установки"/>
        <telerik:GridViewCheckBoxColumn DataMemberBinding="{Binding IsCurrentlyConnected}" Header="Установлено соединение">
            <telerik:GridViewCheckBoxColumn.CellStyle>
                <Style TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
                    <Setter Property="HorizontalContentAlignment" Value="Center" />
                </Style>
            </telerik:GridViewCheckBoxColumn.CellStyle>
        </telerik:GridViewCheckBoxColumn>
    </telerik:RadGridView.Columns>
</telerik:RadGridView>

 

But detail records are not displayed in inner RadGridView yet. Please help.

0
Dmitry
Top achievements
Rank 1
answered on 13 Feb 2017, 07:16 AM

Hello. I write you again. The problem is the same - detail records are NOT DISPLAYED (master records are displayed perfectly). I again show XAML-snippet here (I bag your pardon for Rusian comments):

<Grid.Resources>
            <DataTemplate x:Key="RowDetailsTemplate">
                <telerik:RadGridView Name="SavedSesionsGrid" IsReadOnly="True" ItemsSource="{Binding SavedWorkingSesions}" AutoGenerateColumns="False" ShowGroupPanel="False"
                                     SelectedItem="{Binding SelectedSavedSesion}">
                    <telerik:RadGridView.Columns>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Date}" Header="Дата сессии"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_Begin}" Header="Время начала"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Time_End}" Header="Время окончания"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Modbus_Transmision_Mode}" Header="Режим передачи MODBUS"/>
                        <telerik:GridViewDataColumn DataMemberBinding="{Binding Brief_Description}" Header="Краткое описание" IsReadOnly="False"/>
                    </telerik:RadGridView.Columns>
                </telerik:RadGridView>
            </DataTemplate>
        </Grid.Resources>
         
        <telerik:RadGridView Grid.Row="0" Grid.Column="0" Name="DevicesGrid" ItemsSource="{Binding DevicesWithSavedSesions}" AutoGenerateColumns="False"
                             IsReadOnly="True" CanUserDeleteRows="False" CanUserFreezeColumns="False" CanUserInsertRows="False" CanUserReorderColumns="False"
                             CanUserResizeRows="False" CanUserSearch="False" CanUserSortColumns="False" IsFilteringAllowed="False" SelectedItem="{Binding SelectedDevice}"
                             RowDetailsTemplate="{StaticResource RowDetailsTemplate}" Margin="5">
            <telerik:RadGridView.Columns>
                <telerik:GridViewToggleRowDetailsColumn/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding DisplayedName}" Header="Наименование"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SerialNumber}" Header="Серийный №"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedBeamsQuantity}" Header="Количество лучей"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding SelectedInnerDiameter}" Header="Внутренний диаметр"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding CompanyOwnerOfDevice}" Header="Владелец прибора"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding MountingLocation}" Header="Место установки"/>
                <telerik:GridViewCheckBoxColumn DataMemberBinding="{Binding IsCurrentlyConnected}" Header="Установлено соединение">
                    <telerik:GridViewCheckBoxColumn.CellStyle>
                        <Style TargetType="telerik:GridViewCell" BasedOn="{StaticResource GridViewCellStyle}">
                            <Setter Property="HorizontalContentAlignment" Value="Center" />
                        </Style>
                    </telerik:GridViewCheckBoxColumn.CellStyle>
                </telerik:GridViewCheckBoxColumn>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>

Below is definition of 'SavedWorkingSesions' property:

/// <summary>
/// Gets or sets saved working sessions
/// </summary>
public ObservableCollection<DeviceWorkingSession> SavedWorkingSesions
{
     get { return this._savedWorkingSesions; }
     set { this.SetProperty(ref this._savedWorkingSesions, value); }
}

Below is IConfirmNavigationRequest.OnNavigatedTo method where I populate this collection. Please see below:

public void OnNavigatedTo(NavigationContext navigationContext)
{
    // Set header for table of devices (flowmeters) that have saved working sessions.
    LocalizationManager.Manager = new RecordAndPlaybackLocalizationManager();
 
    // If navigation to the view is the first time navigation after the application was loaded:
    if (this._f_FirstNavigationHere)
    {
        // Get (from SQL Server database table) records about devices that have saved working sessions.
        string errMessage;
        List<Device> devicesWithStorageSessions = this._connectionService.SelectDevicesWithSavedWorkingSessions(out errMessage);
        // If query is successfull:
        if (errMessage == null)
        {
            // If number of records were selected:
            if (devicesWithStorageSessions != null)
            {
                // If the application is connected to some flowmeter now:
                if (GlobalStaticMembers.SharedProfileHeader != null)
                {
                    // Check if connected flowmeter has saved working sesions.
                    // If yes, then set its connection flag.
                    // If no, then add this device to list.
                    Device checkedDevice = devicesWithStorageSessions.FirstOrDefault(elem => elem.Brand == GlobalStaticMembers.SharedProfileHeader.Brand &&
                    elem.Name == GlobalStaticMembers.SharedProfileHeader.Name && elem.SerialNumber == GlobalStaticMembers.SharedProfileHeader.SerialNumber);
                    if (checkedDevice != null)
                        checkedDevice.IsCurrentlyConnected = true;
                    else
                        devicesWithStorageSessions.Add(GlobalStaticMembers.SharedProfileHeader);
                }
                // Read (from SQL Server database) records about saved sesions.
                List<DeviceWorkingSession> savedSessions = this._connectionService.SelectSavedWorkingSesions(out errMessage);
                // If query is successfull:
                if (errMessage == null)
                {
                    // Take next device (flowmeter):
                    foreach (Device device in devicesWithStorageSessions)
                    {
                        // Select all the saved session, this device,
                        foreach (DeviceWorkingSession session in savedSessions)
                        {
                            if (session.Devices_Id == device.Id)
                                device.SavedWorkingSession.Add(session);
                        }
                        // Add this device to binding source collection.
                        this.DevicesWithSavedSesions.Add(device);
                    }
                    // FILL BINDING SOURCE COLLECTION OF SAVED WORKING SESSIONS.
                    ObservableCollection<DeviceWorkingSession> tmpSesionsCol = new ObservableCollection<DeviceWorkingSession>(this.DevicesWithSavedSesions.SelectMany(device => device.SavedWorkingSession));
                    foreach (DeviceWorkingSession session in tmpSesionsCol)
                        this.SavedWorkingSesions.Add(session);
 
 
                }
                else
                    this.raiseNotification("Запрос сохранённых сесий: " + errMessage, "Ошибка");
            }
            else
            {
                // If no devices with saved working sesions:
 
                // Add record about currently connected flowmeter so the user can save its working sesion.
                if (GlobalStaticMembers.SharedProfileHeader != null)
                    this.DevicesWithSavedSesions.Add(GlobalStaticMembers.SharedProfileHeader);
            }
        }
        else
            this.raiseNotification("Запрос приборов с сессиями: " + errMessage, "Ошибка");
        // Reset first time navigation flag.
        this._f_FirstNavigationHere = false;
    }
}

I see in debuger that 'SavedWorkingSesions' (that is detail binding source collection) is filed successfully. But detail records are not displayed. Why? Please help me.

Братушки, помогите.

0
Accepted
Stefan Nenchev
Telerik team
answered on 13 Feb 2017, 02:33 PM
Hello Yaroslav,

As advised in my previous reply, the DataContext of the child RadGridView is the respective item of the parent RadGridView. With this in mind, with your current setup, it seems that you are trying to set the ItemsSource of the inner Grid to a SavedWorkingSessions property on the Device. Looking at your model the Device object exposes a SavedWorkingSession property which is different. If my assumptions are correct - you should see binding errors in the Output Window when running the application similar to this:

System.Windows.Data Error: 40 : BindingExpression path error: 'SavedWorkingSesions' property not found on 'object' ''Device' ...

According to your explanation, you would like to bind the inner grid to a property on the ViewModel. With this in mind, you should explicitly point the source of the binding. Please, try the following in the child RadGridView:

<telerik:RadGridView Name="SavedSesionsGrid"
                                    IsReadOnly="True"
                                    ItemsSource="{Binding DataContext.SavedWorkingSesions, RelativeSource={RelativeSource FindAncestor, AncestorType=telerik:RadGridView}}"}"
                                    AutoGenerateColumns="False"
                                    ShowGroupPanel="False">

I hope it will be helpful.

Regards,
Stefan Nenchev
Telerik by Progress
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 you to write beautiful native mobile apps using a single shared C# codebase.
0
Dmitry
Top achievements
Rank 1
answered on 14 Feb 2017, 05:23 AM
Thank you very much, Stefan. Your help is great. Detail records are displayed.
0
Stefan Nenchev
Telerik team
answered on 14 Feb 2017, 09:32 AM
Hi Yaroslav,

It's great to hear I was of help and the issue is now resolved.

Regards,
Stefan Nenchev
Telerik by Progress
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 you to write beautiful native mobile apps using a single shared C# codebase.
Tags
GridView
Asked by
Dmitry
Top achievements
Rank 1
Answers by
Dmitry
Top achievements
Rank 1
Stefan Nenchev
Telerik team
Share this question
or