通过 XAML 代码居中 WPF RibbonWindow 标题

发布于 2024-12-03 16:00:07 字数 731 浏览 1 评论 0原文

我在 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>

I've found some info on StackOverflow regarding my problem, so I introduced the following XAML code to my window.
Now everything is fine, while the WPF window hasn't quick launch icons or contextual tabs active.

Is there a way to center the application title completely via XAML Code.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦年海沫深 2024-12-10 16:00:07

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

对于其价值,代码如下,但首先请注意:

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

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

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

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

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

在此处输入图像描述

作为比较,这就是如何RibbonWindow 无需自定义即可呈现自身:

在此处输入图像描述

这是它的呈现方式TitleTemplate 定义为带有 TextAlignment="Center"TextBlock,但没有任何花哨的文本效果:

在此处输入图像描述

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

在此处输入图像描述

MainWindow:

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

Here's a very naïve way to do it. It comes about from inspecting the visual tree of a RibbonWindow and its concomitant Ribbon. I've been playing with this code for a couple of hours (and no longer) -- it's a bit rough around the edges and I'm not sure it's completely bug free. There's some optimizations to be made and it should be noted that I suck at WPF; there might be better way to do things.

For what it's worth the code is below, but note first:

  • The references to the PART_Icon template are not directly related to your question, but it is related to the aesthetics of the window.

  • The references to IsWin8OrHigher and FindChild are in classes that I'll include at the end. My interest in Windows 8 is that the native ribbon library centres the title text, whereas earlier versions of Windows do not. I'm trying to emulate that here.

  • I have no idea how the RibbonWindow was shipped with Visual Studio 2012 in its current iteration. The rendering on Windows 8 looks pretty miserable. After all this, I'm tempted to overload TitleTemplate with a TextBlock to get rid of the default glow and leave it at that.

  • The RibbonWindow doesn't look very good maximized, customization or not.

When I started writing this code, this was approximately what I was aiming for:

enter image description here

For comparison, this is how the RibbonWindow renders itself with no customisation:

enter image description here

This is how it renders with TitleTemplate defined to a TextBlock with TextAlignment="Center" but otherwise without any fancy text effects:

enter image description here

With the code below, we get this result:

enter image description here

MainWindow:

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;
    }
}
来日方长 2024-12-10 16:00:07

那应该工作得很好。我刚刚对其进行了测试,标题按其应有的方式居中。

That should be working fine. I've just tested it and the title centers as it should.

乜一 2024-12-10 16:00:07

如果你想让它真正居中,它需要是:

HorizontalAlignment="Center"

if you want it truly centered, it needs to be:

HorizontalAlignment="Center"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文