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

RadDataGrid DataGridComboBoxColumn DisplayMemberPath is not displaying in column.

10 Answers 267 Views
DataGrid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Mike
Top achievements
Rank 1
Mike asked on 08 Dec 2017, 02:20 AM

I have a column in a table that contains an integer which is related to the primary key integer in another collection. In the column instead of displaying the integer, I am trying to display the Name field from the related collection in the grid column. Right now it displays the integer instead of the expected value from DisplayMemberPath.  (The combobox is working as expected when in edit mode.) There are no errors in XAML designer, build process or in debug immediate window. I have tried a number of tweaks and all the docs I can find but nothing has worked. Seems strange combo is working exactly as expected during edit mode but DisplayMemberPath won't show in grid view mode.

<Page.Resources>
    <CollectionViewSource x:Key="cOwners" Source="{x:Bind Owners}"/>
</Page.Resources>
 
<tg:RadDataGrid x:Name="LocationsGrid"
           UserEditMode="Inline"
           ColumnDataOperationsMode="Flyout"
           ItemsSource="{x:Bind Locations}"
           AutoGenerateColumns="False"
           IsTapEnabled="True"
           IsDoubleTapEnabled="True"
           SelectionMode="Single"
           SelectionUnit="Row" >
                 
    <tg:RadDataGrid.Columns>
        <tg:DataGridNumericalColumn PropertyName="Identifier" />
                     
        <tg:DataGridComboBoxColumn PropertyName="OwnerId"              <!--integer in locations collection. -->
                          ItemsSource="{Binding Source={StaticResource cOwners}}"
                          SelectedValuePath="Identifier"  <!--related integer in cOwners collection-->
                          DisplayMemberPath="Name" />     <!--desired column display string from cOwners--> 
 
        <tg:DataGridTextColumn PropertyName="Name" />
        <tg:DataGridTextColumn PropertyName="Address" />
        <tg:DataGridTextColumn PropertyName="City" />
        <tg:DataGridTextColumn PropertyName="State" />
        <tg:DataGridTextColumn PropertyName="PostalCode" />
        <tg:DataGridNumericalColumn PropertyName="Latitude" />
        <tg:DataGridNumericalColumn PropertyName="Longitude" />
        <tg:DataGridTextColumn PropertyName="Description" />
        <tg:DataGridTextColumn PropertyName="Image" />
        <tg:DataGridBooleanColumn PropertyName="Active" />
        <tg:DataGridDateColumn PropertyName="Modified" />
    </tg:RadDataGrid.Columns>
                 
</tg:RadDataGrid>

10 Answers, 1 is accepted

Sort by
0
Yana
Telerik team
answered on 12 Dec 2017, 04:04 PM
Hi Mike,

Actually that's the expected behavior - the DataGrid shows the properties of its ItemsSource, only in edit mode you could see the value set as DisplayMemberPath of the inner ComboBox.

I would suggest you save a reference to the Owner object inside the Location instead of preserving just the OwnerId - in this way you will be able to show the values properly. I've attached a simple example based on your code to demonstrate the approach, please download it and give it a try.

I hope this would be helpful.

Regards,
Yana
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Mike
Top achievements
Rank 1
answered on 13 Dec 2017, 01:44 AM

Yana - Thank you for the insight. I did quite a bit of head banging trying to get this to work in a manner for example the way you would expect a grid with a combobox in MS Access to work. I also appreciate the example offered. The specifications for the data structures though specify that the strings be stored only in their respective primary tables and relationships be based on primary keys. The expectation is that the strings could change slightly over time. By using the integer keys the "Name" can be changed in the primary table and this change would automatically be reflected throughout without having to run update routines on all tables that might contain a reference to the parent record.  Think highly relational data structure. I have been able to accomplish the DisplayMember behavior I'm looking for in a single record form with the standard UWP combobox but not in a grid.

I really like all of the other features of the RadDataGrid so I hate to give up just yet. I don't know maybe I can do something with bringing the string into the grid as an add-on field and hide the integer combobox column. When the row goes into edit mode hide the add-on column and unhide the integer combobox. Then flip it back after edit. The important thing is I know I need to be digging in a different hole.

Mike

0
Yana
Telerik team
answered on 13 Dec 2017, 12:19 PM
Hello Mike,

I am sorry the suggested approach didn't help.

If you find a suitable solution to achieve this scenario, please share it in this thread, I am sure it would be helpful to the community as well.

Regards,
Yana
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
David
Top achievements
Rank 1
answered on 23 Mar 2018, 12:32 PM

Mike's approach does work for this.

I created and additional calculated field in the datasource that contains the Display value for the ID field. I then created two columns in the grid, one a ComboBoxColumn for editing the value, and one a Text column in the grid for the DisplayValue. I then set the visibility of these columns to properties in the ViewModel which are set on BeginEdit and CommitEdit. All works fine.

<tg:DataGridTextColumn PropertyName="cStatus"
                       CanUserEdit="False"
                       Header="Status"
                       SizeMode="Auto"
                       IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingViewed}"
                       />
<tg:DataGridComboBoxColumn PropertyName="Status" Header="Status"
                           ItemsSource="{x:Bind ViewModel.OcPaymentStatus}"
                           DisplayMemberPath="Description"
                           SelectedValuePath="Code"
                           SizeMode="Auto"
                           IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingEdited}"/>
<tg:RadDataGrid.Commands>
    <gridCommands:DataGridUserCommand Id="BeginEdit" Command="{x:Bind Path=PaymentBeginEdit}"/>
    <gridCommands:DataGridUserCommand Id="CommitEdit" Command="{x:Bind Path=PaymentCommitEdit}"/>
    <gridCommands:DataGridUserCommand Id="CancelEdit" Command="{x:Bind Path=PaymentCancelEdit}"/>
</tg:RadDataGrid.Commands>


 

In the code, properties and events

 
private bool _isPaymentBeingEdited = false;
 
public bool IsPaymentBeingEdited
{
    get { return _isPaymentBeingEdited; }
    set
    {
        Set(ref _isPaymentBeingEdited, value);
        IsPaymentBeingViewed = !value;
    }
}
 
private bool _isPaymentBeingViewed = true;
 
public bool IsPaymentBeingViewed
{
    get { return _isPaymentBeingViewed; }
    set
    {
        Set(ref _isPaymentBeingViewed, value);
    }
}
private void OnPaymentBeginEdit(EditContext parameter)
{
    ViewModel.IsPaymentBeingEdited = true;
 
    if (parameter != null && parameter is EditContext)
    {
        EditContext context = (EditContext)parameter;
 
        if (context.CellInfo.Item is Payments)
        {
            ViewModel.PaymentBeingEdited = ((Payments)context.CellInfo.Item).PaymentID;
        }
    }
}
 
private void OnPaymentCommitEdit(EditContext parameter)
{
    if (parameter != null && parameter is EditContext)
    {
        EditContext context = (EditContext)parameter;
 
        if (context.CellInfo.Item is Payments)
        {
                 
Here I refresh the display value of the lookup field
 
            ViewModel.RefreshPaymentLookupValues((Payments)context.CellInfo.Item);
        }
    }
 
    ViewModel.PaymentChangesMade = true;
    ViewModel.IsPaymentBeingEdited = false;
}
private void OnPaymentCancelEdit(EditContext parameter)
{
    ViewModel.IsPaymentBeingEdited = false;
}
 

 

 

 

0
Yana
Telerik team
answered on 26 Mar 2018, 12:49 PM
Hello David,

Thank you for sharing your solution.

Regards,
Yana
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Edmund
Top achievements
Rank 1
answered on 05 Dec 2018, 02:00 AM

Hi,

Please can you elaborate on how this code works or forward the sample code.  For example in the XAML Path=PaymentBeginEdit  where was PaymentBeginEdit defined?

 

Thanks,

Ed

0
David
Top achievements
Rank 1
answered on 05 Dec 2018, 10:05 AM

Hi Ed,

PaymentBeginEdit, PaymentCommitEdit and PaymentCancelEdit at ICommands defined in the code behind the xaml page. I know this doesn't conform to the rules for the ViewModel, but it was the only way I could get it to work:

private ICommand _paymentBeginEdit;
 
public ICommand PaymentBeginEdit
{
    get
    {
        if (_paymentBeginEdit == null)
        {
            _paymentBeginEdit = new RelayCommand<EditContext>(OnPaymentBeginEdit);
        }
 
        return _paymentBeginEdit;
    }
 
}
 
private ICommand _paymentCommitEdit;
 
public ICommand PaymentCommitEdit
{
    get
    {
        if (_paymentCommitEdit == null)
        {
            _paymentCommitEdit = new RelayCommand<EditContext>(OnPaymentCommitEdit);
        }
 
        return _paymentCommitEdit;
    }
 
}
 
private ICommand _paymentCancelEdit;
 
public ICommand PaymentCancelEdit
{
    get
    {
        if (_paymentCancelEdit == null)
        {
            _paymentCancelEdit = new RelayCommand<EditContext>(OnPaymentCancelEdit);
        }
 
        return _paymentCancelEdit;
    }
 
}

 

OnPaymentBeginEdit, OnPaymentCommitEdit & OnPaymentCancelEdit are also in the code behind file. IsPaymentBeingEdited and IsPaymentBeingViewed are in the ViewModel. The other method I did not include, RefreshPaymentLookupValues is also in the ViewModel.cs file

internal void RefreshPaymentLookupValues(Payments payment)
{
    // refreshes the lookup values for status and method on the payment row
 
    payment.cStatus = PoseidonDataService.GetPaymentStatus(payment.Status);
    payment.cMethod = PoseidonDataService.GetPaymentMethod(payment.Method);
}

The editing is managed by a button in one of the grid columns. I don't respond to the button directly, I added a further ICommand to the grid which responds to the CellTap event of the grid. In this I check which column the user taps, and if the edit button column I make the call to BeginEdit.

<tg:DataGridTemplateColumn Name="pgEditColumn"
                           Header=""
                           SizeMode="Auto">
    <tg:DataGridTemplateColumn.CellContentTemplate>
        <DataTemplate>
          <Button HorizontalAlignment="Center"
                  x:Name="pgEditButton" Margin="5"
                  ToolTipService.ToolTip="Edit payment"
                  Style="{StaticResource EditButtonStyle}"/>
        </DataTemplate>
    </tg:DataGridTemplateColumn.CellContentTemplate>
</tg:DataGridTemplateColumn>
<tg:RadDataGrid.Commands>
    <gridCommands:DataGridUserCommand Id="CellTap" Command="{x:Bind Path=PaymentGridCellTap}"/>
    <gridCommands:DataGridUserCommand Id="BeginEdit" Command="{x:Bind Path=PaymentBeginEdit}"/>
    <gridCommands:DataGridUserCommand Id="CommitEdit" Command="{x:Bind Path=PaymentCommitEdit}"/>
    <gridCommands:DataGridUserCommand Id="CancelEdit" Command="{x:Bind Path=PaymentCancelEdit}"/>
</tg:RadDataGrid.Commands>
private ICommand _paymentGridCellTap;
 
public ICommand PaymentGridCellTap
{
    get
    {
        if (_paymentGridCellTap == null)
        {
            _paymentGridCellTap = new RelayCommand<DataGridCellInfo>(OnPaymentGridCellTap(info));
        }
 
        return _paymentGridCellTap;
    }
 
}
private void OnPaymentCellTap(DataGridCellInfo info)
        {
            if (info.Column.Name == "pgEditColumn")
            {
                if (info.Item != null && info.Item is Payments)
                {
                    PaymentsGrid.BeginEdit(info.Item);
                }
             }
        }

I hope this helps. I no longer have the full code I was using then, as I abandoned editing in the grid directly because I had other issues with the size of the rows in edit mode when I had wrapped text, which couldn't be resolved (I think this is still a bug in the grid itself). I instead now use a popup containing a usercontrol to edit the contents of a grid row. More long-winded, but it works.

0
Edmund
Top achievements
Rank 1
answered on 05 Dec 2018, 11:47 PM

Hi David,

 

Thanks a lot for your quick response.  Very helpful I'll give it a try.

 

Regards,

Ed

0
Edmund
Top achievements
Rank 1
answered on 06 Dec 2018, 12:45 AM
[quote]David said:

Hi Ed,

PaymentBeginEdit, PaymentCommitEdit and PaymentCancelEdit at ICommands defined in the code behind the xaml page. I know this doesn't conform to the rules for the ViewModel, but it was the only way I could get it to work:

private ICommand _paymentBeginEdit;
 
public ICommand PaymentBeginEdit
{
    get
    {
        if (_paymentBeginEdit == null)
        {
            _paymentBeginEdit = new RelayCommand<EditContext>(OnPaymentBeginEdit);
        }
 
        return _paymentBeginEdit;
    }
 
}
 
private ICommand _paymentCommitEdit;
 
public ICommand PaymentCommitEdit
{
    get
    {
        if (_paymentCommitEdit == null)
        {
            _paymentCommitEdit = new RelayCommand<EditContext>(OnPaymentCommitEdit);
        }
 
        return _paymentCommitEdit;
    }
 
}
 
private ICommand _paymentCancelEdit;
 
public ICommand PaymentCancelEdit
{
    get
    {
        if (_paymentCancelEdit == null)
        {
            _paymentCancelEdit = new RelayCommand<EditContext>(OnPaymentCancelEdit);
        }
 
        return _paymentCancelEdit;
    }
 
}

 

OnPaymentBeginEdit, OnPaymentCommitEdit & OnPaymentCancelEdit are also in the code behind file. IsPaymentBeingEdited and IsPaymentBeingViewed are in the ViewModel. The other method I did not include, RefreshPaymentLookupValues is also in the ViewModel.cs file

internal void RefreshPaymentLookupValues(Payments payment)
{
    // refreshes the lookup values for status and method on the payment row
 
    payment.cStatus = PoseidonDataService.GetPaymentStatus(payment.Status);
    payment.cMethod = PoseidonDataService.GetPaymentMethod(payment.Method);
}

The editing is managed by a button in one of the grid columns. I don't respond to the button directly, I added a further ICommand to the grid which responds to the CellTap event of the grid. In this I check which column the user taps, and if the edit button column I make the call to BeginEdit.

<tg:DataGridTemplateColumn Name="pgEditColumn"
                           Header=""
                           SizeMode="Auto">
    <tg:DataGridTemplateColumn.CellContentTemplate>
        <DataTemplate>
          <Button HorizontalAlignment="Center"
                  x:Name="pgEditButton" Margin="5"
                  ToolTipService.ToolTip="Edit payment"
                  Style="{StaticResource EditButtonStyle}"/>
        </DataTemplate>
    </tg:DataGridTemplateColumn.CellContentTemplate>
</tg:DataGridTemplateColumn>
<tg:RadDataGrid.Commands>
    <gridCommands:DataGridUserCommand Id="CellTap" Command="{x:Bind Path=PaymentGridCellTap}"/>
    <gridCommands:DataGridUserCommand Id="BeginEdit" Command="{x:Bind Path=PaymentBeginEdit}"/>
    <gridCommands:DataGridUserCommand Id="CommitEdit" Command="{x:Bind Path=PaymentCommitEdit}"/>
    <gridCommands:DataGridUserCommand Id="CancelEdit" Command="{x:Bind Path=PaymentCancelEdit}"/>
</tg:RadDataGrid.Commands>
private ICommand _paymentGridCellTap;
 
public ICommand PaymentGridCellTap
{
    get
    {
        if (_paymentGridCellTap == null)
        {
            _paymentGridCellTap = new RelayCommand<DataGridCellInfo>(OnPaymentGridCellTap(info));
        }
 
        return _paymentGridCellTap;
    }
 
}
private void OnPaymentCellTap(DataGridCellInfo info)
        {
            if (info.Column.Name == "pgEditColumn")
            {
                if (info.Item != null && info.Item is Payments)
                {
                    PaymentsGrid.BeginEdit(info.Item);
                }
             }
        }

I hope this helps. I no longer have the full code I was using then, as I abandoned editing in the grid directly because I had other issues with the size of the rows in edit mode when I had wrapped text, which couldn't be resolved (I think this is still a bug in the grid itself). I instead now use a popup containing a usercontrol to edit the contents of a grid row. More long-winded, but it works.

[/quote]

 

Hi David,

One bit I got stuck on, what do I need for RelayCommand?  Is this something that needs to be included or something you created? Intellisense didn't help with it.

Thanks,

Ed

0
Edmund
Top achievements
Rank 1
answered on 06 Dec 2018, 12:47 AM

Hi,

 

Thanks again.  One further question, where is RelayCommand from, intellisense didn't help.  Was it generated by you or something included.

 

Thanks,

Ed

[quote]David said:

Hi Ed,

PaymentBeginEdit, PaymentCommitEdit and PaymentCancelEdit at ICommands defined in the code behind the xaml page. I know this doesn't conform to the rules for the ViewModel, but it was the only way I could get it to work:

private ICommand _paymentBeginEdit;
 
public ICommand PaymentBeginEdit
{
    get
    {
        if (_paymentBeginEdit == null)
        {
            _paymentBeginEdit = new RelayCommand<EditContext>(OnPaymentBeginEdit);
        }
 
        return _paymentBeginEdit;
    }
 
}
 
private ICommand _paymentCommitEdit;
 
public ICommand PaymentCommitEdit
{
    get
    {
        if (_paymentCommitEdit == null)
        {
            _paymentCommitEdit = new RelayCommand<EditContext>(OnPaymentCommitEdit);
        }
 
        return _paymentCommitEdit;
    }
 
}
 
private ICommand _paymentCancelEdit;
 
public ICommand PaymentCancelEdit
{
    get
    {
        if (_paymentCancelEdit == null)
        {
            _paymentCancelEdit = new RelayCommand<EditContext>(OnPaymentCancelEdit);
        }
 
        return _paymentCancelEdit;
    }
 
}

 

OnPaymentBeginEdit, OnPaymentCommitEdit & OnPaymentCancelEdit are also in the code behind file. IsPaymentBeingEdited and IsPaymentBeingViewed are in the ViewModel. The other method I did not include, RefreshPaymentLookupValues is also in the ViewModel.cs file

internal void RefreshPaymentLookupValues(Payments payment)
{
    // refreshes the lookup values for status and method on the payment row
 
    payment.cStatus = PoseidonDataService.GetPaymentStatus(payment.Status);
    payment.cMethod = PoseidonDataService.GetPaymentMethod(payment.Method);
}

The editing is managed by a button in one of the grid columns. I don't respond to the button directly, I added a further ICommand to the grid which responds to the CellTap event of the grid. In this I check which column the user taps, and if the edit button column I make the call to BeginEdit.

<tg:DataGridTemplateColumn Name="pgEditColumn"
                           Header=""
                           SizeMode="Auto">
    <tg:DataGridTemplateColumn.CellContentTemplate>
        <DataTemplate>
          <Button HorizontalAlignment="Center"
                  x:Name="pgEditButton" Margin="5"
                  ToolTipService.ToolTip="Edit payment"
                  Style="{StaticResource EditButtonStyle}"/>
        </DataTemplate>
    </tg:DataGridTemplateColumn.CellContentTemplate>
</tg:DataGridTemplateColumn>
<tg:RadDataGrid.Commands>
    <gridCommands:DataGridUserCommand Id="CellTap" Command="{x:Bind Path=PaymentGridCellTap}"/>
    <gridCommands:DataGridUserCommand Id="BeginEdit" Command="{x:Bind Path=PaymentBeginEdit}"/>
    <gridCommands:DataGridUserCommand Id="CommitEdit" Command="{x:Bind Path=PaymentCommitEdit}"/>
    <gridCommands:DataGridUserCommand Id="CancelEdit" Command="{x:Bind Path=PaymentCancelEdit}"/>
</tg:RadDataGrid.Commands>
private ICommand _paymentGridCellTap;
 
public ICommand PaymentGridCellTap
{
    get
    {
        if (_paymentGridCellTap == null)
        {
            _paymentGridCellTap = new RelayCommand<DataGridCellInfo>(OnPaymentGridCellTap(info));
        }
 
        return _paymentGridCellTap;
    }
 
}
private void OnPaymentCellTap(DataGridCellInfo info)
        {
            if (info.Column.Name == "pgEditColumn")
            {
                if (info.Item != null && info.Item is Payments)
                {
                    PaymentsGrid.BeginEdit(info.Item);
                }
             }
        }

I hope this helps. I no longer have the full code I was using then, as I abandoned editing in the grid directly because I had other issues with the size of the rows in edit mode when I had wrapped text, which couldn't be resolved (I think this is still a bug in the grid itself). I instead now use a popup containing a usercontrol to edit the contents of a grid row. More long-winded, but it works.

[/quote]
Tags
DataGrid
Asked by
Mike
Top achievements
Rank 1
Answers by
Yana
Telerik team
Mike
Top achievements
Rank 1
David
Top achievements
Rank 1
Edmund
Top achievements
Rank 1
Share this question
or