wpf - 通过 XAML 代码居中 WPF RibbonWindow 标题

标签 wpf templates xaml ribbon title

我在 StackOverflow 上找到了一些有关我的问题的信息,因此我将以下 XAML 代码引入到我的窗口中。 现在一切都很好,但 WPF 窗口没有快速启动图标或上下文选项卡处于事件状态。

有没有办法通过XAML代码使应用程序标题完全居中。

<ribbon:Ribbon.TitleTemplate>
    <DataTemplate>
        <TextBlock TextAlignment="Center" HorizontalAlignment="Stretch"
            Width="{Binding ElementName=Window, Path=ActualWidth}">ApplicationTitle
            <TextBlock.Effect>
               <DropShadowEffect ShadowDepth="0" Color="MintCream " BlurRadius="10"/>   
            </TextBlock.Effect>
        </TextBlock>
    </DataTemplate>           
</ribbon:Ribbon.TitleTemplate>

最佳答案

这是一种非常幼稚的方法。它来自于检查 RibbonWindow 及其伴随的 Ribbon 的可视化树。我已经使用这段代码几个小时了(现在已经不再了)——它的边缘有点粗糙,我不确定它是否完全没有错误。需要进行一些优化,并且应该指出的是,我对 WPF 很烂;可能有更好的方法来做事。

代码如下,但首先请注意:

  • PART_Icon 模板的引用与您的问题没有直接关系,但与窗口的美观有关。

  • IsWin8OrHigherFindChild 的引用位于我将在最后包含的类中。我对 Windows 8 的兴趣在于, native 功能区库将标题文本居中,而早期版本的 Windows 则不然。我试图在这里模仿这一点。

  • 我不知道 RibbonWindow 是如何在当前版本的 Visual Studio 2012 中附带的。 Windows 8 上的渲染看起来非常糟糕。毕竟,我很想用 TextBlock 重载 TitleTemplate 来摆脱默认发光并保留它。

  • RibbonWindow 最大化后看起来不太好,无论是否自定义。

当我开始编写这段代码时,这大约是我的目标:

enter image description here

为了进行比较,这是 RibbonWindow 在没有自定义的情况下呈现自身的方式:

enter image description here

这是使用 TitleTemplate 定义到 TextBlock 并使用 TextAlignment="Center" 进行渲染的方式,但没有任何花哨的文本效果:

enter image description here

使用下面的代码,我们得到这个结果:

enter image description here

主窗口:

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

关于wpf - 通过 XAML 代码居中 WPF RibbonWindow 标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7345422/

相关文章:

c# - 让我的 wpf 应用程序全屏(覆盖窗口的任务栏和标题栏)

c# - 预加载 WPF 窗口(可能在其他线程中)以提高性能

c++ - 确定模板参数是否为指针

c++ - 为什么在 C++ 中使用关系运算符创建的模板函数不能正确处理字符串?

c# - VS2017 中的 XAML 中的 DesignInstance 在设计时不显示数据

wpf - 如何在 WPF 菜单控件上设置前景色和背景色?

c# - 播放后强制 MediaElement 释放流

看起来像 3DSMAX 的 WPF 3D 编辑器

C++ 模板 :-Warning in a function template

c# - 有条件地绑定(bind)到 Xamarin XAML MVVM 中的两个不同命令