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' 值设置。一旦我将模式添加到该绑定中,标签就会在用户登录时开始更新,并且根本不需要任何外部代码:)