在 AppBar 中隐藏省略号
Hiding the ellipsis within an AppBar
当您在 UWP 应用程序中创建 AppBar 或 CommandBar 时,总会有一个省略号隐藏在控件的一侧,如下所示:
我不想在我的应用程序中使用它,但我在 AppBar
中没有找到任何 methods/properties 可以帮助我摆脱它。应该是可以的,因为很多默认的 Windows 10 应用都没有。例如,下面的主菜单栏上没有省略号:
是否可以使用 AppBar
隐藏省略号,或者我是否必须使用 SplitView
或其他控件来实现此功能?
首先,尽量不要在您的新 UWP 应用程序中使用 AppBar
。
The CommandBar control for universal Windows apps has been improved to
provide a superset of AppBar functionality and greater flexibility in
how you can use it in your app. You should use CommandBar for all new
universal Windows apps on Windows 10.
您可以阅读更多相关信息 here。
CommandBar
和 AppBar
都可以进行完整样式化和模板化。这使您能够删除任何不想显示的 UI 元素。
这就是你的做法 -
在 Blend 中打开您的页面,右键单击 CommandBar
> 编辑模板 > 编辑副本。然后确保你 select 在应用程序中定义 因为目前 Blend 中有一个错误,如果你选择 This document[=43= 将无法生成样式].
一旦你拥有所有样式,找到 MoreButton
控件并将其 Visibility
设置为 Collapsed
(或者你可以删除它,但如果你意识到以后需要它怎么办? ).
那么你应该有一个没有省略号的CommandBar
。
2017 年更新
现在可以在 CommandBar
的 OverflowButtonVisibility
属性 中找到省略号按钮的可见性。如上将其设置为 Collapsed
以隐藏它。
如果你想全局隐藏这个按钮,添加
<Style x:Key="EllipsisButton" TargetType="Button">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
到全局资源文件
我知道这个问题不再有效,但为了完成,我提出了我的答案。
我编写了一个 AttachedProperty 扩展,能够通过数据绑定 hide/show MoreButton,而不是通过使用样式来更改可见性。这样你就可以 show/hide 有条件地随心所欲。
使用方法很简单,只需将 属性 绑定到扩展程序即可:
<CommandBar extensions:CommandBarExtensions.HideMoreButton="{Binding MyBoolean}">
...
</CommandBar>
扩展代码如下:
public static class CommandBarExtensions
{
public static readonly DependencyProperty HideMoreButtonProperty =
DependencyProperty.RegisterAttached("HideMoreButton", typeof(bool), typeof(CommandBarExtensions),
new PropertyMetadata(false, OnHideMoreButtonChanged));
public static bool GetHideMoreButton(UIElement element)
{
if (element == null) throw new ArgumentNullException(nameof(element));
return (bool)element.GetValue(HideMoreButtonProperty);
}
public static void SetHideMoreButton(UIElement element, bool value)
{
if (element == null) throw new ArgumentNullException(nameof(element));
element.SetValue(HideMoreButtonProperty, value);
}
private static void OnHideMoreButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var commandBar = d as CommandBar;
if (e == null || commandBar == null || e.NewValue == null) return;
var morebutton = commandBar.FindDescendantByName("MoreButton");
if (morebutton != null)
{
var value = GetHideMoreButton(commandBar);
morebutton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
}
else
{
commandBar.Loaded += CommandBarLoaded;
}
}
private static void CommandBarLoaded(object o, object args)
{
var commandBar = o as CommandBar;
var morebutton = commandBar?.FindDescendantByName("MoreButton");
if (morebutton == null) return;
var value = GetHideMoreButton(commandBar);
morebutton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
commandBar.Loaded -= CommandBarLoaded;
}
}
在初始绑定时,它使用 Loaded 事件在加载后应用隐藏。 FindDescendantByName
是另一种迭代可视化树的扩展方法。如果您的解决方案尚未包含它,您可能想要创建或获取它。
由于我无法对特定答案添加评论,因此我将在此处 post。
下页给出了很多例子,可以找到子对象来赞美@RadiusK的回答。
How can I find WPF controls by name or type?
在 UWP 中特别适合我的是:
/// <summary>
/// Finds a Child of a given item in the visual tree.
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found,
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null)
return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null)
break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
像这样调用代码:
var morebutton = FindChild<Button>(commandBar, "MoreButton");
在@RadiusK 的回答(有一些问题)的基础上,我想出了一个经过测试并且有效的更简洁的替代方案:
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace Linq
{
public static class CommandBarExtensions
{
public static readonly DependencyProperty HideMoreButtonProperty = DependencyProperty.RegisterAttached("HideMoreButton", typeof(bool), typeof(CommandBarExtensions), new PropertyMetadata(false, OnHideMoreButtonChanged));
public static bool GetHideMoreButton(CommandBar d)
{
return (bool)d.GetValue(HideMoreButtonProperty);
}
public static void SetHideMoreButton(CommandBar d, bool value)
{
d.SetValue(HideMoreButtonProperty, value);
}
static void OnHideMoreButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var CommandBar = d as CommandBar;
if (CommandBar != null)
{
var MoreButton = CommandBar.GetChild<Button>("MoreButton") as UIElement;
if (MoreButton != null)
{
MoreButton.Visibility = !(e.NewValue as bool) ? Visibility.Visible : Visibility.Collapsed;
}
else CommandBar.Loaded += OnCommandBarLoaded;
}
}
static void OnCommandBarLoaded(object sender, RoutedEventArgs e)
{
var CommandBar = sender as CommandBar;
var MoreButton = CommandBar?.GetChild<Button>("MoreButton") as UIElement;
if (MoreButton != null)
{
MoreButton.Visibility = !(GetHideMoreButton(CommandBar) as bool) ? Visibility.Visible : Visibility.Collapsed;
CommandBar.Loaded -= OnCommandBarLoaded;
}
}
public static T GetChild<T>(this DependencyObject Parent, string Name) where T : DependencyObject
{
if (Parent != null)
{
for (int i = 0, Count = VisualTreeHelper.GetChildrenCount(Parent); i < Count; i++)
{
var Child = VisualTreeHelper.GetChild(Parent, i);
var Result = Child is T && !string.IsNullOrEmpty(Name) && (Child as FrameworkElement)?.Name == Name ? Child as T : Child.GetChild<T>(Name);
if (Result != null)
return Result;
}
}
return null;
}
}
}
当您在 UWP 应用程序中创建 AppBar 或 CommandBar 时,总会有一个省略号隐藏在控件的一侧,如下所示:
我不想在我的应用程序中使用它,但我在 AppBar
中没有找到任何 methods/properties 可以帮助我摆脱它。应该是可以的,因为很多默认的 Windows 10 应用都没有。例如,下面的主菜单栏上没有省略号:
是否可以使用 AppBar
隐藏省略号,或者我是否必须使用 SplitView
或其他控件来实现此功能?
首先,尽量不要在您的新 UWP 应用程序中使用 AppBar
。
The CommandBar control for universal Windows apps has been improved to provide a superset of AppBar functionality and greater flexibility in how you can use it in your app. You should use CommandBar for all new universal Windows apps on Windows 10.
您可以阅读更多相关信息 here。
CommandBar
和 AppBar
都可以进行完整样式化和模板化。这使您能够删除任何不想显示的 UI 元素。
这就是你的做法 -
在 Blend 中打开您的页面,右键单击 CommandBar
> 编辑模板 > 编辑副本。然后确保你 select 在应用程序中定义 因为目前 Blend 中有一个错误,如果你选择 This document[=43= 将无法生成样式].
一旦你拥有所有样式,找到 MoreButton
控件并将其 Visibility
设置为 Collapsed
(或者你可以删除它,但如果你意识到以后需要它怎么办? ).
那么你应该有一个没有省略号的CommandBar
。
2017 年更新
现在可以在 CommandBar
的 OverflowButtonVisibility
属性 中找到省略号按钮的可见性。如上将其设置为 Collapsed
以隐藏它。
如果你想全局隐藏这个按钮,添加
<Style x:Key="EllipsisButton" TargetType="Button">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
到全局资源文件
我知道这个问题不再有效,但为了完成,我提出了我的答案。
我编写了一个 AttachedProperty 扩展,能够通过数据绑定 hide/show MoreButton,而不是通过使用样式来更改可见性。这样你就可以 show/hide 有条件地随心所欲。
使用方法很简单,只需将 属性 绑定到扩展程序即可:
<CommandBar extensions:CommandBarExtensions.HideMoreButton="{Binding MyBoolean}">
...
</CommandBar>
扩展代码如下:
public static class CommandBarExtensions
{
public static readonly DependencyProperty HideMoreButtonProperty =
DependencyProperty.RegisterAttached("HideMoreButton", typeof(bool), typeof(CommandBarExtensions),
new PropertyMetadata(false, OnHideMoreButtonChanged));
public static bool GetHideMoreButton(UIElement element)
{
if (element == null) throw new ArgumentNullException(nameof(element));
return (bool)element.GetValue(HideMoreButtonProperty);
}
public static void SetHideMoreButton(UIElement element, bool value)
{
if (element == null) throw new ArgumentNullException(nameof(element));
element.SetValue(HideMoreButtonProperty, value);
}
private static void OnHideMoreButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var commandBar = d as CommandBar;
if (e == null || commandBar == null || e.NewValue == null) return;
var morebutton = commandBar.FindDescendantByName("MoreButton");
if (morebutton != null)
{
var value = GetHideMoreButton(commandBar);
morebutton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
}
else
{
commandBar.Loaded += CommandBarLoaded;
}
}
private static void CommandBarLoaded(object o, object args)
{
var commandBar = o as CommandBar;
var morebutton = commandBar?.FindDescendantByName("MoreButton");
if (morebutton == null) return;
var value = GetHideMoreButton(commandBar);
morebutton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
commandBar.Loaded -= CommandBarLoaded;
}
}
在初始绑定时,它使用 Loaded 事件在加载后应用隐藏。 FindDescendantByName
是另一种迭代可视化树的扩展方法。如果您的解决方案尚未包含它,您可能想要创建或获取它。
由于我无法对特定答案添加评论,因此我将在此处 post。
下页给出了很多例子,可以找到子对象来赞美@RadiusK的回答。
How can I find WPF controls by name or type?
在 UWP 中特别适合我的是:
/// <summary>
/// Finds a Child of a given item in the visual tree.
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found,
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null)
return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null)
break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
像这样调用代码:
var morebutton = FindChild<Button>(commandBar, "MoreButton");
在@RadiusK 的回答(有一些问题)的基础上,我想出了一个经过测试并且有效的更简洁的替代方案:
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace Linq
{
public static class CommandBarExtensions
{
public static readonly DependencyProperty HideMoreButtonProperty = DependencyProperty.RegisterAttached("HideMoreButton", typeof(bool), typeof(CommandBarExtensions), new PropertyMetadata(false, OnHideMoreButtonChanged));
public static bool GetHideMoreButton(CommandBar d)
{
return (bool)d.GetValue(HideMoreButtonProperty);
}
public static void SetHideMoreButton(CommandBar d, bool value)
{
d.SetValue(HideMoreButtonProperty, value);
}
static void OnHideMoreButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var CommandBar = d as CommandBar;
if (CommandBar != null)
{
var MoreButton = CommandBar.GetChild<Button>("MoreButton") as UIElement;
if (MoreButton != null)
{
MoreButton.Visibility = !(e.NewValue as bool) ? Visibility.Visible : Visibility.Collapsed;
}
else CommandBar.Loaded += OnCommandBarLoaded;
}
}
static void OnCommandBarLoaded(object sender, RoutedEventArgs e)
{
var CommandBar = sender as CommandBar;
var MoreButton = CommandBar?.GetChild<Button>("MoreButton") as UIElement;
if (MoreButton != null)
{
MoreButton.Visibility = !(GetHideMoreButton(CommandBar) as bool) ? Visibility.Visible : Visibility.Collapsed;
CommandBar.Loaded -= OnCommandBarLoaded;
}
}
public static T GetChild<T>(this DependencyObject Parent, string Name) where T : DependencyObject
{
if (Parent != null)
{
for (int i = 0, Count = VisualTreeHelper.GetChildrenCount(Parent); i < Count; i++)
{
var Child = VisualTreeHelper.GetChild(Parent, i);
var Result = Child is T && !string.IsNullOrEmpty(Name) && (Child as FrameworkElement)?.Name == Name ? Child as T : Child.GetChild<T>(Name);
if (Result != null)
return Result;
}
}
return null;
}
}
}