这是一种非常幼稚的方法。它来自于检查 RibbonWindow 及其伴随的 Ribbon 的可视化树。我已经用这个代码玩了几个小时(并且不再)——它的边缘有点粗糙,我不确定它是否完全没有错误。有一些优化要做,应该注意的是我很讨厌 WPF;可能有更好的方法来做事。
代码如下,但首先要注意:
-
对PART_Icon模板的引用与你的问题没有直接关系,但与窗口的美观有关。
-
对IsWin8OrHigher 和FindChild 的引用位于我将在最后包含的类中。我对 Windows 8 的兴趣在于本机功能区库以标题文本为中心,而早期版本的 Windows 则没有。我试图在这里效仿。
-
我不知道 RibbonWindow 在当前迭代中是如何与 Visual Studio 2012 一起提供的。 Windows 8 上的渲染看起来很糟糕。毕竟,我很想用TextBlock 重载TitleTemplate 以摆脱默认发光并保持不变。
-
RibbonWindow 看起来不是很好最大化,无论是否自定义。
当我开始编写这段代码时,这大致就是我的目标:
作为比较,这是RibbonWindow 在没有自定义的情况下呈现自己的方式:
这是它的渲染方式,TitleTemplate 定义为 TextBlock 和 TextAlignment="Center",但没有任何花哨的文本效果:
通过下面的代码,我们得到了这个结果:
主窗口:
public partial class MainWindow {
public MainWindow() {
InitializeComponent();
if (Environment.OSVersion.IsWin8OrHigher()) {
SizeChanged += (sender, args) => TitleHack();
Activated += (sender, args) => TitleHack();
}
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
if (!Environment.OSVersion.IsWin8OrHigher())
return;
var icon = GetTemplateChild("PART_Icon") as Image;
if (icon == null)
return;
icon.Margin = new Thickness(icon.Margin.Left + 3, icon.Margin.Top + 2,
icon.Margin.Right, icon.Margin.Bottom);
}
private void TitleHack() {
var ribbonTitlePanel = MyRibbon.FindChild<FrameworkElement>("PART_TitlePanel");
var qatTopHost = MyRibbon.FindChild<FrameworkElement>("QatTopHost");
var titleHost = MyRibbon.FindChild<FrameworkElement>("PART_TitleHost");
var tabGroup = MyRibbon.FindChild<FrameworkElement>("PART_ContextualTabGroupItemsControl");
var qatTopHostLeft = qatTopHost.TransformToAncestor(ribbonTitlePanel).Transform(new Point(0, 0)).X;
var tabGroupLeft = tabGroup.TransformToAncestor(ribbonTitlePanel).Transform(new Point(0, 0)).X;
var width = ribbonTitlePanel.ActualWidth;
if (tabGroup.Visibility == Visibility.Visible) {
width -= tabGroup.ActualWidth;
width -= tabGroupLeft - qatTopHostLeft;
} else {
width -= qatTopHost.ActualWidth;
}
if (ResizeMode != ResizeMode.NoResize && WindowStyle != WindowStyle.None)
width -= 48; // For the min and max buttons
titleHost.Width = width > 0 ? width : Double.NaN;
}
}
OperatingSystemExtensionMethods.cs:
public static class OperatingSystemExtensionMethods {
private static readonly Version Windows8Version = new Version(6, 2);
public static bool IsWin8OrHigher(this OperatingSystem that) {
if (that.Platform != PlatformID.Win32NT)
return false;
return that.Version.CompareTo(Windows8Version) >= 0;
}
}
DependencyObjectExtensionMethods.cs:
public static class DependencyObjectExtensionMethods {
public static T FindChild<T>(this DependencyObject that, string elementName)
where T : FrameworkElement {
var childrenCount = VisualTreeHelper.GetChildrenCount(that);
for (var i = 0; i < childrenCount; i++) {
var child = VisualTreeHelper.GetChild(that, i);
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && elementName == frameworkElement.Name)
return (T) frameworkElement;
if ((frameworkElement = frameworkElement.FindChild<T>(elementName)) != null)
return (T) frameworkElement;
}
return null;
}
}