FirstFloor ModernUI无法通过titlelink . linknavigator导航



当按下键盘快捷键时,我试图通过以下代码导航到XAML控件(特别是ModernFrame控件):

LinkNavigator.Navigate(new Uri("/Controls/SettingsManager.xaml", UriKind.Relative), this);

键盘快捷键触发,然后我得到一个异常:

System.ArgumentException: 'Unable to navigate to /Controls/SettingsManager.xaml, could not find a ModernFrame target '''

以下是SettingsManager作为ModernFrame的源代码——注意,如果将其更改为UserControl,它仍然有效。我将其更改为ModernFrame,因为前面提到的异常正在寻找ModernFrame

现在SettingsManager.xaml控件的功能非常好,如果我通过窗口内的TitleLink导航到它。然而,当我试图以编程方式导航到它时,我收到了异常。您可以让控件完全为空,而异常仍然会被抛出。

SettingsManager.xaml.cs:

using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using FirstFloor.ModernUI.Presentation;
using FirstFloor.ModernUI.Windows.Controls;
using KeystoneEstimating.Containers;
namespace KeystoneEstimating.Controls {
/// <summary>
/// Interaction logic for SettingsManager.xaml
/// </summary>
public partial class SettingsManager : ModernFrame {
public SettingsManager() {
InitializeComponent();

/// Load settings into the Link interface of MUI.
List<AppSettings> settings = AppInfo.SettingsContainers;
foreach (AppSettings set in settings) {
Link lnk = new Link();
lnk.DisplayName = set.SettingsName;
lnk.Source = set.ControlPath;
SettingsLinks.Links.Add(lnk);
}
// Load up the very first registered settings page.
if (SettingsLinks.Links.First() != null)
SettingsLinks.SelectedSource = SettingsLinks.Links.First().Source;
}
}
}

SettingsManage.xaml:

<mui:ModernFrame xmlns:mui="http://firstfloorsoftware.com/ModernUI"
x:Class="KeystoneEstimating.Controls.SettingsManager"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:local="clr-namespace:KeystoneEstimating"
mc:Ignorable="d" 
d:DesignHeight="300" d:DesignWidth="300">
<Grid Style="{StaticResource ContentRoot}">
<mui:ModernTab Layout="List" Name="SettingsLinks"/>
</Grid>
</mui:ModernFrame>

ModernUI有两个nugetpackage,标记为ModernUI.WPFCore。一个是2.0.0版本,另一个是3.1.2版本。

似乎有一个固有的问题与FirstFloor ModernUI的导航命令,它找不到主窗口。当调用Navigate()时,xaml的ContentFrameModernFrame类型的样式控件。

我从源代码中搜索了样式,发现通过XAML可以通过WPF绑定找到ContentFrame

<Button Content="{Binding DisplayName}"
Command="navigation:LinkCommands.NavigateLink"
CommandParameter="{Binding Source}"
CommandTarget="{Binding ElementName=ContentFrame}"
Style="{StaticResource SystemButtonLink}" />

当你点击ModernWindow中的任何Link时,这就是代码的处理方式,当你在XAML中预编码UI元素时,它就会完美地工作,因为所有XAML元素都会自动继承ModernWindow作为它们的父对象。这对于导航命令是必需的,因为它要搜索父元素的元素层次结构,以找到要填充的ModernFrame。参见DefaultLinkNavigator.Navigate调用函数NavigationHelper.FindFrame(parameter, source):

/// <summary>
/// Finds the frame identified with given name in the specified context.
/// </summary>
/// <param name="name">The frame name.</param>
/// <param name="context">The framework element providing the context for finding a frame.</param>
/// <returns>The frame or null if the frame could not be found.</returns>
public static ModernFrame FindFrame(string name, FrameworkElement context)
{
if (context == null) {
throw new ArgumentNullException("context");
}
// collect all ancestor frames
var frames = context.AncestorsAndSelf().OfType<ModernFrame>().ToArray();
if (name == null || name == FrameSelf) {
// find first ancestor frame
return frames.FirstOrDefault();
}
if (name == FrameParent) {
// find parent frame
return frames.Skip(1).FirstOrDefault();
}
if (name == FrameTop) {
// find top-most frame
return frames.LastOrDefault();
}
// find ancestor frame having a name matching the target
var frame = frames.FirstOrDefault(f => f.Name == name);

if (frame == null) {
// find frame in context scope
frame = context.FindName(name) as ModernFrame;
if (frame == null) {
// find frame in scope of ancestor frame content
var parent = frames.FirstOrDefault();
if (parent != null && parent.Content != null) {
var content = parent.Content as FrameworkElement;
if (content != null) {
frame = content.FindName(name) as ModernFrame;
}
}
}
}
return frame;
}

然而,在代码中不是这样的…当在代码中执行链接时,您希望导航到的控件的XAML页面还不存在,因此没有父控件,不能用于在导航中查找父控件的ModernFrame

然而,解决方案是要么在代码中创建绑定并将绑定作为参数传递给导航命令-我还不知道如何做-或者对ModernWindow控件进行分层搜索,并手动搜索类型为ModernFrame的所有源元素,名称为ContentFrame(这是ModernWindow.xaml中显示内容的窗口的显示元素)。

首先在MainWindow.cs类中添加一个分层搜索功能——它应该扩展ModernWindow而不是WPF中的Window:

public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject {
// Confirm parent and childName are valid. 
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++) {
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null) {
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child. 
if (foundChild != null) break;
} else if (!string.IsNullOrEmpty(childName)) {
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName) {
// if the child's name is of the request name
foundChild = (T)child;
break;
}
} else {
// child element found.
foundChild = (T)child;
break;
}
}

在同一个类中通过代码导航到控件——在我的例子中是执行键绑定时——可以使用三种不同的方法:

var target = FindChild<ModernFrame>(this, "ContentFrame");
// A:
LinkCommands.NavigateLink.Execute(new Uri("/Controls/SettingsManager.xaml", UriKind.RelativeOrAbsolute), target);

// B:
NavigationCommands.GoToPage.Execute("/Controls/SettingsManager.xaml", target);

// C:
this.LinkNavigator.Navigate(new Uri("/Controls/SettingsManager.xaml", UriKind.Relative), target as FrameworkElement);

层次子搜索的来源:https://stackoverflow.com/a/1759923/2808956

相关内容

  • 没有找到相关文章