In my MainWindow I have a FlowDocumentScrollViewer
binding its property Document
to a FlowDocument
in my MainViewModel.
This document is loaded from an external xaml file store on a remote computer. Currently I'm able to load this document properly via XamlReader.Load(xamlfile)
and display it in the FlowDocumentScrollViewer
. So far so good.
The problem occurs when I try to add hyperlink in this document. Because to handle the RequestNavigate
event I need a x:Class
. For the time being this Class need to be my MainWindow
because the event is handle in the code-behind. Obviously when I add x:Class="Ugrader.MainWindow"
in my external document I get a lovely 'System.Windows.Markup.XamlParseException'
at the moment of parsing.
So is there a way to solve this ?
Here is piece of my code
<Window x:Class="Ugrader.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Geco3-Upgrading version"
WindowStyle="none" ResizeMode="NoResize" ShowInTaskbar="False" WindowStartupLocation="CenterScreen"
Height="400" Width="700"
DataContext="{Binding Main,Source={StaticResource Locator}}">
<FlowDocumentScrollViewer Grid.Column="1" Background="{x:Null}" VerticalScrollBarVisibility="Hidden"
Document="{Binding WhatsNewDoc}"/>
</Window>
namespace Ugrader.ViewModel
{
public class MainViewModel : ViewModelBase
{
#region Constructor
public MainViewModel()
{
try
{
FileStream xamlFile = new FileStream(updateLocation + "whatsnew.xaml", FileMode.Open, FileAccess.Read);
FlowDocument current = System.Windows.Markup.XamlReader.Load(xamlFile) as FlowDocument;
WhatsNewDoc = current;
}
catch (Exception)
{
}
}
#endregion
#region Properties
private FlowDocument _watsNewDoc = new FlowDocument();
public FlowDocument WhatsNewDoc
{
get
{
return _watsNewDoc;
}
set
{
if(_watsNewDoc != value)
{
_watsNewDoc = value;
RaisePropertyChanged("WhatsNewDoc");
}
}
}
#endregion
}
}
<FlowDocument x:Class="Ugrader.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ColumnWidth="400" FontSize="12" FontFamily="Century Gothic" Foreground="LightGray">
<Paragraph>
<Italic>
For additionnal information, please watch this
<Hyperlink TextDecorations="{x:Null}" RequestNavigate="Hyperlink_Clicked" NavigateUri="path_to_the_file" >video</Hyperlink>
</Italic>
</Paragraph>
</FlowDocument>
By the way, is there a way to handle this parse exception (in case of bad external file), because even in this try/catch block, this stop my program.
Thanks you in advance,
Bastien.
I find a way to deal with my problem, it's not really beautiful, do not respect the spirit of mvvm, but well, this is working.
So, as it's not possible to add x:Class
at runtime (I guess), I came to the idea of handling the RequestNavigate
event of each Hyperlink
at runtime. So the solution is pretty simple (and dirty).
In code-behind (yeah I know, it's ugly), on the MainWindow
loaded event, I find all hyperlinks in my document, and handle each RequestNavigate
events. As simple (and dirty) as this.
Here is some code :
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var hyperlinks = GetVisuals(this).OfType<Hyperlink>();
foreach (var link in hyperlinks)
link.RequestNavigate += link_RequestNavigate;
}
public static IEnumerable<DependencyObject> GetVisuals(DependencyObject root)
{
foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
{
yield return child;
foreach (var descendants in GetVisuals(child))
yield return descendants;
}
}
If someone has a better solution, I take it.