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
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
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
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
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)
{
ViewModel.RefreshPaymentLookupValues((Payments)context.CellInfo.Item);
}
}
ViewModel.PaymentChangesMade =
true
;
ViewModel.IsPaymentBeingEdited =
false
;
}
private
void
OnPaymentCancelEdit(EditContext parameter)
{
ViewModel.IsPaymentBeingEdited =
false
;
}
Thank you for sharing your solution.
Regards,
Yana
Progress Telerik
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
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.
Hi David,
Thanks a lot for your quick response. Very helpful I'll give it a try.
Regards,
Ed
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
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]