UWP Community Tookit 动态 HamburgerMenuGlyphItem 标签
UWP Community Tookit dynamic HamburgerMenuGlyphItem labels
我使用社区工具包实现了一个汉堡包菜单,开始时效果很好。
我现在正在尝试添加更改菜单中项目的功能。
例如,我希望 OptionItems 之一显示登录状态。
如果没有登录我希望它说登录,如果他们是我希望它显示他们的名字。
我尝试在标签中添加标准 x:Bind 但它不起作用:
<controls:HamburgerMenuGlyphItem Label="{x:Bind Path=UserProfileViewModel.UserName}" Tag="SignIn" Glyph="Contact" />
在 Hamburger 菜单外的 TextBlock 上使用完全相同的绑定效果很好,一旦用户登录就会显示用户名。
有人知道如何在 MenuItems 中实现绑定吗?
Anyone have any idea how to implement binding within the MenuItems?
您可以将 HamburgerMenu 的 ItemsSource 设置为 IEnumerable 并绑定到 ItemTemplate 中类型 T 的 属性。
查看:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Name="ItemTemplate" x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Symbol}" />
<TextBlock Grid.Column="1" Text="{x:Bind Label, Mode=TwoWay}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:HamburgerMenu x:Name="hamburgerMenuControl"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
ItemTemplate="{StaticResource ItemTemplate}"
ItemClick="hamburgerMenuControl_ItemClick">
<ContentControl Content="{Binding SelectedItem.Content}" />
</controls:HamburgerMenu>
</Grid>
</Page>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = new ViewModel();
}
private void hamburgerMenuControl_ItemClick(object sender, ItemClickEventArgs e)
{
//workaround to set the SelectedItem property of the view model when a new item is selected
(DataContext as ViewModel).SelectedItem = e.ClickedItem as Item;
}
}
查看模型:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Items.Add(new Item() { Label = "1", Symbol = Symbol.Bullets, Content = "1..." });
Items.Add(new Item() { Label = "2", Symbol = Symbol.Bullets, Content = "2..." });
Items.Add(new Item() { Label = "3", Symbol = Symbol.Bullets, Content = "3..." });
SelectedItem = Items[0];
}
public IList<Item> Items { get; } = new List<Item>();
private Item _selectedItem;
public Item SelectedItem
{
get { return _selectedItem; }
set { _selectedItem = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
型号:
public class Item : INotifyPropertyChanged
{
private string _label;
public string Label
{
get { return _label; }
set { _label = value; NotifyPropertyChanged(); }
}
public Symbol Symbol { get; set; }
public object Content { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
将模型的标签 属性 设置为用户名或您希望在选项菜单中显示的任何内容。这就是您使用推荐的 MVVM 设计模式对 HamburgerMenu 进行数据绑定的方式。
如果您直接在视图的 XAML 标记中定义 HamburgerMenuGlyphItems,您可以在同一视图的代码隐藏中以编程方式绑定设置绑定:
<controls:HamburgerMenuGlyphItem x:Name="item" />
public MainPage()
{
this.InitializeComponent();
BindingOperations.SetBinding(item, HamburgerMenuGlyphItem.LabelProperty,
new Binding() { Path = new PropertyPath(nameof(Username)), Source = this });
}
public string Username { get; } = "username...";
}
所以mm8提供的方案确实有效。
然而,在让它工作的过程中,我发现了如何解决最初的问题而无需付出任何额外的努力。
将 Mode=TwoWay(OneWay 也适用)添加到 DataTemplate 中的 TextBlock 绑定解决了在 属性 更改时让标签更新的问题。
然后我发现 HamburgerMenuGlyphItem 本身的数据绑定也需要这个 'Mode' 值设置。一旦我将模式添加到该绑定中,标签就会在用户登录时开始更新,并且根本不需要任何外部代码:)
我使用社区工具包实现了一个汉堡包菜单,开始时效果很好。 我现在正在尝试添加更改菜单中项目的功能。 例如,我希望 OptionItems 之一显示登录状态。 如果没有登录我希望它说登录,如果他们是我希望它显示他们的名字。 我尝试在标签中添加标准 x:Bind 但它不起作用:
<controls:HamburgerMenuGlyphItem Label="{x:Bind Path=UserProfileViewModel.UserName}" Tag="SignIn" Glyph="Contact" />
在 Hamburger 菜单外的 TextBlock 上使用完全相同的绑定效果很好,一旦用户登录就会显示用户名。
有人知道如何在 MenuItems 中实现绑定吗?
Anyone have any idea how to implement binding within the MenuItems?
您可以将 HamburgerMenu 的 ItemsSource 设置为 IEnumerable 并绑定到 ItemTemplate 中类型 T 的 属性。
查看:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Name="ItemTemplate" x:DataType="local:Item">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Symbol}" />
<TextBlock Grid.Column="1" Text="{x:Bind Label, Mode=TwoWay}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:HamburgerMenu x:Name="hamburgerMenuControl"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
ItemTemplate="{StaticResource ItemTemplate}"
ItemClick="hamburgerMenuControl_ItemClick">
<ContentControl Content="{Binding SelectedItem.Content}" />
</controls:HamburgerMenu>
</Grid>
</Page>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = new ViewModel();
}
private void hamburgerMenuControl_ItemClick(object sender, ItemClickEventArgs e)
{
//workaround to set the SelectedItem property of the view model when a new item is selected
(DataContext as ViewModel).SelectedItem = e.ClickedItem as Item;
}
}
查看模型:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Items.Add(new Item() { Label = "1", Symbol = Symbol.Bullets, Content = "1..." });
Items.Add(new Item() { Label = "2", Symbol = Symbol.Bullets, Content = "2..." });
Items.Add(new Item() { Label = "3", Symbol = Symbol.Bullets, Content = "3..." });
SelectedItem = Items[0];
}
public IList<Item> Items { get; } = new List<Item>();
private Item _selectedItem;
public Item SelectedItem
{
get { return _selectedItem; }
set { _selectedItem = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
型号:
public class Item : INotifyPropertyChanged
{
private string _label;
public string Label
{
get { return _label; }
set { _label = value; NotifyPropertyChanged(); }
}
public Symbol Symbol { get; set; }
public object Content { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
将模型的标签 属性 设置为用户名或您希望在选项菜单中显示的任何内容。这就是您使用推荐的 MVVM 设计模式对 HamburgerMenu 进行数据绑定的方式。
如果您直接在视图的 XAML 标记中定义 HamburgerMenuGlyphItems,您可以在同一视图的代码隐藏中以编程方式绑定设置绑定:
<controls:HamburgerMenuGlyphItem x:Name="item" />
public MainPage()
{
this.InitializeComponent();
BindingOperations.SetBinding(item, HamburgerMenuGlyphItem.LabelProperty,
new Binding() { Path = new PropertyPath(nameof(Username)), Source = this });
}
public string Username { get; } = "username...";
}
所以mm8提供的方案确实有效。 然而,在让它工作的过程中,我发现了如何解决最初的问题而无需付出任何额外的努力。 将 Mode=TwoWay(OneWay 也适用)添加到 DataTemplate 中的 TextBlock 绑定解决了在 属性 更改时让标签更新的问题。 然后我发现 HamburgerMenuGlyphItem 本身的数据绑定也需要这个 'Mode' 值设置。一旦我将模式添加到该绑定中,标签就会在用户登录时开始更新,并且根本不需要任何外部代码:)