Вот очень наивный способ сделать это.Это происходит из проверки визуального дерева RibbonWindow
и его сопутствующего Ribbon
.Я играл с этим кодом в течение нескольких часов (и больше) - он немного грубоват, и я не уверен, что в нем нет ошибок.Нужно сделать некоторые оптимизации, и следует отметить, что я отстой в WPF;мог бы быть лучший способ сделать что-то.
Для чего стоит код ниже, но обратите внимание:
Ссылки на шаблон PART_Icon
не являютсянепосредственно связан с вашим вопросом, но он связан с эстетикой окна.
Ссылки на IsWin8OrHigher
и FindChild
находятся в классах, которые я включу в конце,Мой интерес к Windows 8 заключается в том, что собственная библиотека ленточных носителей центрирует текст заголовка, тогда как в более ранних версиях Windows этого нет.Я пытаюсь подражать этому здесь.
Я понятия не имею, как RibbonWindow
был поставлен с Visual Studio 2012 в его текущей итерации.Рендеринг на Windows 8 выглядит довольно печально.После всего этого у меня возникает соблазн перегрузить TitleTemplate
TextBlock
, чтобы избавиться от свечения по умолчанию и оставить его на этом.
RibbonWindow
невыглядело очень хорошо, развернуто или нет.
Когда я начал писать этот код, это было примерно то, к чему я стремился:
Для сравнения, вот как RibbonWindow
отображает себя без настройки:
Это то, как он обрабатывает с TitleTemplate
, определенным для TextBlock
с TextAlignment="Center"
, но без каких-либо необычных текстовых эффектов:
С помощью приведенного ниже кода мы получим следующий результат:
MainWindow.cs
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;
}
}