3

I am using WPF Modern UI and I am trying to pop up a ModernDialog after clicking a Link. The problem is that a link have only Source option and i don't want to nevigate to another page (just want to pop up a ModernDialog). I found this: How to open a new window click on a menu link in Modern UI wpf? but it only pop up the window at the first click, and it also nevigate to the first tab pages (I mean to the "parent" of the page i looked on).

Does anyone have an idea? is it possible?

This is my code (the relevant part), and I am talking about "connect" link:

 <mui:ModernWindow.TitleLinks>
        <mui:Link x:Name="connect" DisplayName="connect"/>
        <mui:Link DisplayName="settings" Source="/Pages/SettingsPage.xaml" />
        <mui:Link DisplayName="help" Source="https://github.com" />
    </mui:ModernWindow.TitleLinks>
Ben
  • 201
  • 1
  • 4
  • 13

2 Answers2

2

You could override the OnApplyTemplate() method of the ModernWindow and add a NavigateLink command binding to the ModernFrame. The command parameter will be null if you don't set the Source property of the Link:

public partial class MainWindow : ModernWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var frame = Template.FindName("ContentFrame", this) as ModernFrame;
        if(frame != null)
            frame.CommandBindings.Add(new CommandBinding(FirstFloor.ModernUI.Windows.Navigation.LinkCommands.NavigateLink, OnNavigateLinkExecuted));
    }

    private void OnNavigateLinkExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        if(e.Parameter == null)
        {
            ModernDialog dialog = new ModernDialog();
            dialog.ShowDialog();
        }
        else
        {
            OnNavigateLink(sender, e);
        }
    }

    private void OnNavigateLink(object sender, ExecutedRoutedEventArgs e)
    {
        if (LinkNavigator != null)
        {
            Uri uri;
            string parameter;
            string targetName;

            if (FirstFloor.ModernUI.Windows.Navigation.NavigationHelper.TryParseUriWithParameters(e.Parameter, out uri, out parameter, out targetName))
                LinkNavigator.Navigate(uri, e.Source as FrameworkElement, parameter);
        }
    }
}

XAML:

<mui:ModernWindow.TitleLinks>
    <mui:Link x:Name="connect" DisplayName="connect"/>
    <mui:Link DisplayName="settings" Source="/Pages/SettingsPage.xaml" />
    <mui:Link DisplayName="help" Source="https://github.com" />
</mui:ModernWindow.TitleLinks>
mm8
  • 163,881
  • 10
  • 57
  • 88
1

I'd take a different approach.

When your MainWindow is loaded, find the ModernFrame and hook the Navigating event.

In the Navigating event handler, check if the source starts with "dialog:" (arbitrary string, use whatever you want) then show your dialog and cancel the navigation.

The link's Source is set to "dialog:Test" to indicate that I want to show the "Test" dialog.

MainWindow.xaml

<mui:ModernWindow x:Class="WpfApp17.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:mui="http://firstfloorsoftware.com/ModernUI"
        xmlns:local="clr-namespace:WpfApp17"
        mc:Ignorable="d"
        Loaded="ModernWindow_Loaded"
        ContentSource="/UserControl1.xaml"
        Title="MainWindow" Height="350" Width="525">
    <mui:ModernWindow.TitleLinks>
        <mui:Link x:Name="connect" DisplayName="connect" Source="dialog:Test" />
    </mui:ModernWindow.TitleLinks>
</mui:ModernWindow>

MainWindow.xaml.cs

using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using FirstFloor.ModernUI.Windows.Controls;

namespace WpfApp17
{
    public partial class MainWindow : ModernWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ModernWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var frame = VisualTreeHelperFindChildren<ModernFrame>(this).FirstOrDefault();
            if (frame != null)
                frame.Navigating += Frame_Navigating;
        }

        private void Frame_Navigating(object sender, FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            string dialog = "dialog:";
            if (e.Source.OriginalString.StartsWith(dialog))
            {
                // Show dialog
                var dialogName = e.Source.OriginalString.Remove(0, dialog.Length);
                MessageBox.Show($"Show Dialog '{dialogName}'");
                e.Cancel = true;
            }
        }

        public static List<T> VisualTreeHelperFindChildren<T>(DependencyObject parent) where T : class
        {
            List<T> list = new List<T>();

            if (parent != null)
            {
                int count = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < count; i++)
                {
                    // Get object at index i
                    DependencyObject dobj = VisualTreeHelper.GetChild(parent, i);

                    if (dobj is T)
                    {
                        list.Add(dobj as T);
                    }

                    // Loop through its children
                    list.AddRange(VisualTreeHelperFindChildren<T>(dobj));
                }
            }
            return list;
        }

    }
}

BTW - UserControl1.xaml just has a textblock on it and nothing else. I added it so that something was on the screen.

J.H.
  • 4,232
  • 1
  • 18
  • 16