Requests with GridHyperlinkColumn
Hello,
I use a SfDataGrid and I would like to use the GridHyperlinkColumn to navigate to the detail's page of a row.
But I meet 2 problems:
1 - the rendering of the cell:
in your samples, the cell has a different color, so the user undetstands that he must click here:


but in my app, it's not the case:


I tried to set the style directly as described here, but this didn't change anything...
how-to-style-hyperlink-column
how-to-style-hyperlink-column
=> would you have an idea?
2 - navigate through the ViewModel:
The GridHyperlinkColumn uses the CurrentCellRequestNavigate event to raises the navigation.
=> I can use Messenger to interact with my ViewModel, but is there a proper way to do it through a Command and the ViewModel?
SIGN IN To post a reply.
15 Replies
JG
Jai Ganesh S
Syncfusion Team
November 7, 2016 11:13 AM UTC
Hi Christophe,
Please find the response for your queries as below,
Query 1:
We have checked the reported issue in our sample but its working fine in our end.
|
<Style TargetType="HyperlinkButton">
<Setter Property="Foreground" Value="Green" />
</Style> |
If still issue occurs, then could you please let us know, how you generate the columns in SfDataGrid and share the more details. This would be more helpful for us to analyze the issue further.
Query 2:
You can wiring the CurrentCellRequestNavigate event through command in viewmodel by using below code,
|
<interact:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="CurrentCellRequestNavigate">
<core:InvokeCommandAction Command="{Binding CurrentCellRequestNavigateCommand}" />
</core:EventTriggerBehavior>
</interact:Interaction.Behaviors>
public void Navigate(object args)
{
string str = "http://www.Syncfusion.com";
Launcher.LaunchUriAsync(new Uri(str));
} |
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfDataGridDemo810231854.zip
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
November 30, 2016 08:59 AM UTC
Thanks for your response.
Your sample works for me too, but it's not the case of my my project.
My XAML looks like this:
Your sample works for me too, but it's not the case of my my project.
My XAML looks like this:
<!-- DataGrid --> <grid:SfDataGrid x:Name="sfDataGrid" Grid.Row="1" Padding="0,10,0,0" ItemsSource="{Binding Forms}" SelectedItem="{Binding SelectedForm, Mode=TwoWay}" AutoGenerateColumns="False" ColumnSizer="Star" NavigationMode="Row" HeaderRowHeight="50"> <grid:SfDataGrid.Columns> <!-- Form Number --> <grid:GridHyperlinkColumn MappingName="form_code" helpers:SfDgColumnSizerAttachedProperty.ColumnSizer="2"> <grid:GridHyperlinkColumn.HeaderTemplate> <DataTemplate> <TextBlock x:Uid="HomeSfColumnFormCodeTextBlock" TextAlignment="Center" TextWrapping="Wrap" /> </DataTemplate> </grid:GridHyperlinkColumn.HeaderTemplate> </grid:GridHyperlinkColumn> <!-- Submitter --> <grid:GridTextColumn x:Uid="HomeSfColumnSubmitter" MappingName="submitterName" helpers:SfDgColumnSizerAttachedProperty.ColumnSizer="3"/> <!-- Company --> <grid:GridTextColumn x:Uid="HomeSfColumnCompany" MappingName="company" /> <!-- Submission date --> <grid:GridTextColumn DisplayBinding="{Binding validation_date, Converter={StaticResource DateFormatConverter}}" helpers:SfDgColumnSizerAttachedProperty.ColumnSizer="2"> <grid:GridTextColumn.HeaderTemplate> <DataTemplate> <TextBlock x:Uid="HomeSfColumnSubmissionDateTextBlock" TextAlignment="Center" TextWrapping="Wrap" /> </DataTemplate> </grid:GridTextColumn.HeaderTemplate> </grid:GridTextColumn> <!-- Status --> <grid:GridTextColumn x:Uid="HomeSfColumnStatus" MappingName="statusLabel" helpers:SfDgColumnSizerAttachedProperty.ColumnSizer="2"/> <!-- ... more columns --> </grid:SfDataGrid.Columns> </grid:SfDataGrid> |
=> the content of the GridHyperlinkColumn is always displayed without any accent color, but I can well click in the content to navigate to my details page.
I also tried to apply a custom style to the HyperlinkButton, but it didn't change anything:
I also tried to apply a custom style to the HyperlinkButton, but it didn't change anything:
<grid:SfDataGrid.Resources> <Style TargetType="HyperlinkButton"> <Setter Property="Foreground" Value="Red" /> </Style> </grid:SfDataGrid.Resources> |
I specify that content of the column is not a URL, but just a string: the "id" of the form that is opened when the user click on it's name.
For doing this, I use the "OnSfDataGridCurrentCellRequestNavigate":
For doing this, I use the "OnSfDataGridCurrentCellRequestNavigate":
async void OnSfDataGridCurrentCellRequestNavigate(object sender, CurrentCellRequestNavigateEventArgs args) { var form = args.RowData as Forms; var viewModel = this.DataContext as HomeViewModel; viewModel.ClickedForm = form; viewModel.OpenForm(); } |
=> this works well, so I don't understand why I encounter a problem with the render of the GridHyperlinkColumn...
Thanks in advance for your return!
Pierre-Christophe
JG
Jai Ganesh S
Syncfusion Team
December 1, 2016 12:44 PM UTC
Hi Christophe,
We suspect that you have write the style for TextBlock in your application. Hence the HyperLinkColumn Foreground color is not applied.
Could you please check this in your end and please share your Xaml file or if possible please replicate the issue in our sample? This would be more helpful for us to analyze further.
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
December 1, 2016 03:18 PM UTC
Yes you're right: I have redefined the TextBlock default style, to globally affect a specific "font color" to the app. Then I use TextBlock style as base for some "specific" TextBlocks.
This is a part of the style:
<Style TargetType="TextBlock"> <Setter Property="Foreground" Value="{StaticResource FontColor}" /> </Style> <Style x:Key="AppTitleTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}"> <Setter Property="Margin" Value="12,6,0,6" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <Style x:Key="ParagraphTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BodyTextBlockStyle}"> <Setter Property="Margin" Value="0,1,0,34" /> <Setter Property="TextWrapping" Value="Wrap" /> <Setter Property="TextTrimming" Value="CharacterEllipsis" /> </Style> <Style x:Key="TitleTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}"> <Setter Property="Margin" Value="0,1,0,18" /> </Style> ... |
=> Is it possible to keep my custom TextBlock style? Or do I neet to remove it to use the GridHyperlinkColumn style?
Regards,
JG
Jai Ganesh S
Syncfusion Team
December 5, 2016 10:13 AM UTC
Hi Christophe,
You can achieve your requirement to apply the style for GridHyperLinkColumn by customizing the GridCellHyperLinkRenderer and clear the TextBlock style like below,
|
this.sfGrid.CellRenderers.Remove("Hyperlink");
this.sfGrid.CellRenderers.Add("Hyperlink", new CustomCellRendererExt());
public class CustomCellRendererExt : GridCellHyperlinkRenderer
{
public override void OnInitializeEditElement(DataColumnBase dataColumn, HyperlinkButton uiElement, object dataContext)
{
base.OnInitializeEditElement(dataColumn, uiElement, dataContext);
var column = dataColumn.GridColumn;
uiElement.SetValue(FrameworkElement.MarginProperty, column.Padding);
uiElement.SetValue(Control.PaddingProperty, column.Padding);
uiElement.SetValue(Control.VerticalAlignmentProperty, column.VerticalAlignment);
var hyperLinkColumn = (GridHyperlinkColumn)column;
var textBlock = new TextBlock();
uiElement.Content = textBlock;
textBlock.SetBinding(TextBlock.TextProperty, column.ValueBinding);
if (hyperLinkColumn == null)
return;
textBlock.Style = null;
textBlock.SetValue(TextBlock.TextWrappingProperty, hyperLinkColumn.TextWrapping);
uiElement.SetValue(TextBlock.TextWrappingProperty, hyperLinkColumn.TextWrapping);
uiElement.SetValue(Control.HorizontalAlignmentProperty, hyperLinkColumn.HorizontalAlignment);
}
} |
Sample: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfDataGridDemo566427339.zip
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
January 12, 2017 11:28 AM UTC
Thanks for your sample.
But is there a way to render the content of the HyperLinkButton always underlined, as a hyperlink?
SR
Sivakumar R
Syncfusion Team
January 13, 2017 01:08 PM UTC
Hi Christophe,
You can show underlined text in GridHyperlinkColumn by overriding GridCellHyperlinkRenderer as in the below code, We have modified the sample also,
|
public class CustomCellRendererExt : GridCellHyperlinkRenderer
{
public override bool CanUpdateBinding(GridColumn column)
{
return true;
}
public override void OnUpdateEditBinding(DataColumnBase dataColumn, HyperlinkButton element, object dataContext)
{
var textblock = element.Content as TextBlock;
if (textblock == null || textblock.Inlines.Count == 0)
return;
var underline = textblock.Inlines[0] as Underline;
var run = underline.Inlines[0] as Run;
var displayval = this.DataGrid.View.GetPropertyAccessProvider().GetFormattedValue(dataContext, dataColumn.GridColumn.MappingName);
run.Text = displayval == null ? string.Empty : displayval.ToString();
base.OnUpdateEditBinding(dataColumn, element, dataContext);
}
public override void OnInitializeEditElement(DataColumnBase dataColumn, HyperlinkButton uiElement, object dataContext)
{
base.OnInitializeEditElement(dataColumn, uiElement, dataContext);
var column = dataColumn.GridColumn;
uiElement.SetValue(FrameworkElement.MarginProperty, column.Padding);
uiElement.SetValue(Control.PaddingProperty, column.Padding);
uiElement.SetValue(Control.VerticalAlignmentProperty, column.VerticalAlignment);
var hyperLinkColumn = (GridHyperlinkColumn)column;
var textBlock = new TextBlock();
uiElement.Content = textBlock;
//textBlock.SetBinding(TextBlock.TextProperty, column.ValueBinding);
if (hyperLinkColumn == null)
return;
var underline = new Underline();
var run = new Run();
var displayval = this.DataGrid.View.GetPropertyAccessProvider().GetFormattedValue(dataContext, dataColumn.GridColumn.MappingName);
run.Text = displayval == null ? string.Empty : displayval.ToString();
underline.Inlines.Add(run);
textBlock.Inlines.Add(underline);
textBlock.Style = null;
textBlock.SetValue(TextBlock.TextWrappingProperty, hyperLinkColumn.TextWrapping);
uiElement.SetValue(TextBlock.TextWrappingProperty, hyperLinkColumn.TextWrapping);
uiElement.SetValue(Control.HorizontalAlignmentProperty, hyperLinkColumn.HorizontalAlignment);
}
} |
Sample:
Thanks,
Sivakumar
PD
Pierre-Christophe DUS
February 3, 2017 08:32 AM UTC
Thanks for your feedback: this works now fine!
But I have a new request: is it possible to rendering "clickable" the full cell containing the GridHyperlinkColumn?
For exemple all the green area:

For exemple all the green area:

JG
Jai Ganesh S
Syncfusion Team
February 8, 2017 03:14 AM UTC
Hi Christophe,
You can achieve your requirement to do the navigation while clicking anywhere of the GridHyperlinkCell by override the SetFocus method and call the navigation url directly in it.
|
protected async override void SetFocus(FrameworkElement uiElement, bool needToFocus)
{
base.SetFocus(uiElement, needToFocus);
var hyperlinkControl = (HyperlinkButton)uiElement;
GridCell gridcell = null;
if (hyperlinkControl.Parent is GridCell)
gridcell = hyperlinkControl.Parent as GridCell;
var navigateText = string.Empty;
var rowColumnIndex = RowColumnIndex.Empty;
rowColumnIndex.RowIndex = gridcell != null ? gridcell.ColumnBase.RowIndex : new RowColumnIndex().RowIndex;
rowColumnIndex.ColumnIndex = gridcell != null ? gridcell.ColumnBase.ColumnIndex : new RowColumnIndex().ColumnIndex;
if (rowColumnIndex != null && !rowColumnIndex.IsEmpty)
{
//Get the column from rowColumnIndex.
var column = this.DataGrid.Columns[this.DataGrid.ResolveToGridVisibleColumnIndex(rowColumnIndex.ColumnIndex)];
var recordIndex = this.DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);
if (recordIndex < 0)
return;
var record1 = this.DataGrid.View.Records.GetItemAt(recordIndex);
navigateText = record1.GetType().GetProperty(column.MappingName).GetValue(record1).ToString();
}
const string pattern = @"((http|https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)";
if (navigateText != null)
{
var NavigateUri = Regex.IsMatch("http://www.Syncfusion.com", pattern)
? new Uri("http://www.Syncfusion.com")
: null;
if (NavigateUri == null)
return;
hyperlinkControl.NavigateUri = NavigateUri;
await Launcher.LaunchUriAsync(new Uri(hyperlinkControl.NavigateUri.AbsoluteUri));
}
} |
In the above sample, we have set the navigation url inside the SetFocus method and in this case the CurrentCellRequestNavigate event will not be fired while clicking other part of the cell.
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
March 27, 2017 01:46 PM UTC
Hello,
I'm sorry to come back a few weeks after your reply, but I need more help.
In your sample, you use the CurrentCellRequestNavigateCommand Command and the Navigate() method for both cases: the click on the label of the GridHypeLinkColumn and the click outside of the label.
But I don't see how to adapt the code to make it works with paramters. I would like to specify the current id of the row for the clicked cell.
Regards,
I'm sorry to come back a few weeks after your reply, but I need more help.
In your sample, you use the CurrentCellRequestNavigateCommand Command and the Navigate() method for both cases: the click on the label of the GridHypeLinkColumn and the click outside of the label.
But I don't see how to adapt the code to make it works with paramters. I would like to specify the current id of the row for the clicked cell.
Is it possible by basing on your last sample?
Until now, I was doing this:
But in your sample, the SetFocus() method is not in the same classe, so I can't access directly to my ViewModel...
async void OnSfDataGridCurrentCellRequestNavigate(object sender, CurrentCellRequestNavigateEventArgs args)
{
var carForm = args.RowData as Car_Forms;
var viewModel = this.DataContext as HomeViewModel;
viewModel.ClickedCarForm = carForm;
viewModel.OpenForm();
}
Regards,
JG
Jai Ganesh S
Syncfusion Team
March 29, 2017 11:17 AM UTC
Hi Christophe,
You can achieve your requirement to passing the parameters while calling the CurrentCellRequestNavigate event by raising the CurrentCellRequestNavigate event with parameters in SetFocus method like below,
|
protected async override void SetFocus(FrameworkElement uiElement, bool needToFocus)
{
base.SetFocus(uiElement, needToFocus);
var hyperlinkControl = (HyperlinkButton)uiElement;
hyperlinkControl.FontStretch = Windows.UI.Text.FontStretch.UltraExpanded;
GridCell gridcell = null;
if (hyperlinkControl.Parent is GridCell)
gridcell = hyperlinkControl.Parent as GridCell;
var navigateText = string.Empty;
var rowColumnIndex = RowColumnIndex.Empty;
rowColumnIndex.RowIndex = gridcell != null ? gridcell.ColumnBase.RowIndex : new RowColumnIndex().RowIndex;
rowColumnIndex.ColumnIndex = gridcell != null ? gridcell.ColumnBase.ColumnIndex : new RowColumnIndex().ColumnIndex;
if (rowColumnIndex != null && !rowColumnIndex.IsEmpty)
{
//Get the column from rowColumnIndex.
var column = this.DataGrid.Columns[this.DataGrid.ResolveToGridVisibleColumnIndex(rowColumnIndex.ColumnIndex)];
var recordIndex = this.DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);
if (recordIndex < 0)
return;
var record1 = this.DataGrid.View.Records.GetItemAt(recordIndex);
navigateText = record1.GetType().GetProperty(column.MappingName).GetValue(record1).ToString();
}
MethodInfo dynMethod = this.DataGrid.GetType().GetMethod("CurrentCellRequestNavigateEvent",
BindingFlags.NonPublic | BindingFlags.Instance);
CurrentCellRequestNavigateEventArgs ob = new CurrentCellRequestNavigateEventArgs(DataGrid);
ob.GetType().GetProperty("NavigateText").SetValue(ob, navigateText);
ob.GetType().GetProperty("RowData").SetValue(ob, hyperlinkControl.DataContext);
ob.GetType().GetProperty("RowColumnIndex").SetValue(ob, rowColumnIndex);
dynMethod.Invoke(DataGrid, new object[] { ob });
} |
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
March 30, 2017 09:00 AM UTC
Thank you, it's almost perfect like that!
The last problem is that the Navigate() method of the ViewModel is called 2 times when the user click on the hyperlink.
Is there a way to fix this properly, or do I need to add a boolean to disabled the navigation?
Regards,
The last problem is that the Navigate() method of the ViewModel is called 2 times when the user click on the hyperlink.
Is there a way to fix this properly, or do I need to add a boolean to disabled the navigation?
Regards,
JG
Jai Ganesh S
Syncfusion Team
March 31, 2017 10:50 AM UTC
Hi Christophe,
In our sample, we have raised the CurrentCellRequestNavigateEvent from the SetFocus method to achieve your requirement. Hence the Navigate method calling two times. However, you can resolve this by using the flag like below,
|
private bool isNavigate = false;
public void Navigate(object args)
{
if (!isNavigate)
{
string str = "http://www.Syncfusion.com";
Launcher.LaunchUriAsync(new Uri(str));
isNavigate = true;
}
} |
Regards,
Jai Ganesh S
PD
Pierre-Christophe DUS
March 31, 2017 02:03 PM UTC
Thanks again for your feedback.
I have on more question: in my case, I use the SfDataGrid with the NavigationMode="Row", as the grid is only used for displaying data:

But if we use this parameter in your sample, the SetFocus() is not longer fired when a user click in the cell:
But if we remove this parameter, there is a "border" around the current cell:

Is is possible to remove this border?
Or do we can update the code to make it work with the parameter NavigationMode="Row"?

But if we use this parameter in your sample, the SetFocus() is not longer fired when a user click in the cell:
<syncfusion:SfDataGrid x:Name="sfGrid"
Grid.Row="1"
NavigationMode="Row"
SelectionMode="Extended"
AddNewRowPosition="Top"
AllowEditing="True"
AllowFiltering="True"
AutoGenerateColumns="False"
GridValidationMode="InView"
ItemsSource="{Binding UserDetails}"
ShowRowHeader="True">
But if we remove this parameter, there is a "border" around the current cell:

Is is possible to remove this border?
Or do we can update the code to make it work with the parameter NavigationMode="Row"?
JG
Jai Ganesh S
Syncfusion Team
April 3, 2017 10:45 AM UTC
Hi Christophe,
The SetFocus() method will not be fired when the NavigationMode as Row. This is the default behavior of SfDataGrid. However, you can achieve your requirement for removing curentcell border by setting CurrentCellBorderThickness as 0,
|
<syncfusion:SfDataGrid x:Name="sfGrid"
Grid.Row="1"
SelectionMode="Extended"
AddNewRowPosition="Top"
AllowEditing="True"
AllowFiltering="True"
CurrentCellBorderThickness="0"
AutoGenerateColumns="False"
GridValidationMode="InView"
ItemsSource="{Binding UserDetails}"
ShowRowHeader="True"/> |
Regards,
Jai Ganesh S
SIGN IN To post a reply.
- 15 Replies
- 3 Participants
-
PD Pierre-Christophe DUS
- Nov 4, 2016 09:51 AM UTC
- Apr 3, 2017 10:45 AM UTC