0

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

MainWindow.xaml

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

MainViewModel.cs

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
    }
}

The external FlowDocument

<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.

1 Answer 1

1

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 Hyperlinkat 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.