We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy.
Unfortunately, activation email could not send to your email. Please try again.

Requests with GridHyperlinkColumn

Thread ID:

Created:

Updated:

Platform:

Replies:

127233 Nov 4,2016 05:51 AM Apr 3,2017 06:45 AM UWP 15
loading
Tags: SfDataGrid
Pierre-Christophe DUS
Asked On November 4, 2016 05:51 AM

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:
sample

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

I tried to set the style directly as described here, but this didn't change anything...
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?





Jai Ganesh S [Syncfusion]
Replied On November 7, 2016 06:13 AM

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)); 
        } 
 
Regards, 
Jai Ganesh S 


Pierre-Christophe DUS
Replied On November 30, 2016 03:59 AM

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:
<!-- 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:
<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":
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

Jai Ganesh S [Syncfusion]
Replied On December 1, 2016 07:44 AM

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 


Pierre-Christophe DUS
Replied On December 1, 2016 10:18 AM

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,





Jai Ganesh S [Syncfusion]
Replied On December 5, 2016 05:13 AM

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); 
    } 
}  
 
 
Regards, 
Jai Ganesh S 


Pierre-Christophe DUS
Replied On January 12, 2017 06:28 AM

Thanks for your sample.
But is there a way to render the content of the HyperLinkButton always underlined, as a hyperlink?

Sivakumar R [Syncfusion]
Replied On January 13, 2017 08:08 AM

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 


Pierre-Christophe DUS
Replied On February 3, 2017 03:32 AM

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:
Request

Jai Ganesh S [Syncfusion]
Replied On February 7, 2017 10:14 PM

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 


Pierre-Christophe DUS
Replied On March 27, 2017 09:46 AM

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.
Is it possible by basing on your last sample?

Until now, I was doing this:
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();
}

But in your sample, the SetFocus() method is not in the same classe, so I can't access directly to my ViewModel...

Regards,

Jai Ganesh S [Syncfusion]
Replied On March 29, 2017 07:17 AM

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 


Pierre-Christophe DUS
Replied On March 30, 2017 05:00 AM

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,


Jai Ganesh S [Syncfusion]
Replied On March 31, 2017 06:50 AM

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 


Pierre-Christophe DUS
Replied On March 31, 2017 10:03 AM

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:
<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"?





Jai Ganesh S [Syncfusion]
Replied On April 3, 2017 06:45 AM

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 


CONFIRMATION

This post will be permanently deleted. Are you sure you want to continue?

Sorry, An error occured while processing your request. Please try again later.

You are using an outdated version of Internet Explorer that may not display all features of this and other websites. Upgrade to Internet Explorer 8 or newer for a better experience.

;