【问题标题】:Center WPF RibbonWindow Title via XAML Code通过 XAML 代码居中 WPF RibbonWindow 标题
【发布时间】:2011-09-08 08:46:35
【问题描述】:

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

【问题讨论】:

  • +1 我一直在想办法绕过RibbonWindow 附带的可怕的默认标题模板。这给了我一个解决方法。不过,我发现您在使用快速访问工具栏和上下文选项卡时遇到了问题。
  • 查看窗口的可视化树,标题部分最终位于DockPanel 中。据我所知,它们没有提供那么多布局功能。
  • 潜在问题是功能区使用RibbonTitlePanel 和专有布局算法,将标题放置在任何上下文选项卡的右侧。我想您可以从RibbonTitlePanel 派生一个类并提供更好的布局算法,但是要将其挂接到Ribbon 控件中,您需要修改Ribbon 控件模板,并且只获取该模板的副本似乎是一项艰巨的任务。

标签: wpf templates xaml ribbon title


【解决方案1】:

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

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

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

  • IsWin8OrHigherFindChild 的引用位于我将在最后包含的类中。我对 Windows 8 的兴趣在于本机功能区库以标题文本为中心,而早期版本的 Windows 则没有。我试图在这里效仿。

  • 我不知道 RibbonWindow 在当前迭代中是如何与 Visual Studio 2012 一起提供的。 Windows 8 上的渲染看起来很糟糕。毕竟,我很想用TextBlock 重载TitleTemplate 以摆脱默认发光并保持不变。

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

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

作为比较,这是RibbonWindow 在没有自定义的情况下呈现自己的方式:

这是它的渲染方式,TitleTemplate 定义为 TextBlockTextAlignment="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;
    }
}

【讨论】:

    【解决方案2】:

    这应该可以正常工作。我刚刚对其进行了测试,并且标题居中。

    【讨论】:

    • i 您没有任何上下文选项卡处于活动状态,这很好,但是在上下文选项卡处于活动状态时,它会以上下文选项卡末尾开始的其余宽度为中心。我正在寻找以整个标题栏为中心的解决方案。
    【解决方案3】:

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

    HorizontalAlignment="Center"
    

    【讨论】:

      猜你喜欢
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多