【问题标题】:UWP Community Tookit dynamic HamburgerMenuGlyphItem labelsUWP 社区工具包动态 HamburgerMenuGlyphItem 标签
【发布时间】:2016-12-09 14:49:42
【问题描述】:

我已经使用社区工具包实现了一个汉堡菜单,该工具包开始很好。 我现在正在尝试添加更改菜单中项目的功能。 例如,我希望其中一个 OptionItems 显示登录状态。 如果没有登录,我希望它说登录,如果他们是,我希望它显示他们的名字。 我尝试将标准 x:Bind 添加到标签,但它不起作用:

<controls:HamburgerMenuGlyphItem Label="{x:Bind Path=UserProfileViewModel.UserName}" Tag="SignIn" Glyph="Contact" />

在汉堡菜单外的 TextBlock 上使用完全相同的绑定可以正常工作,一旦登录就会显示用户名。

有人知道如何在 MenuItems 中实现绑定吗?

【问题讨论】:

    标签: uwp uwp-xaml windows-community-toolkit


    【解决方案1】:

    有人知道如何在 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));
    }
    

    将模型的 Label 属性设置为用户名或您希望在选项菜单中显示的任何内容。这就是您使用推荐的 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...";
    }
    

    【讨论】:

    • 您好,感谢您的建议,但我无法使其正常工作。创建了一个新的解决方案并使用了提供的代码。将 INotifyPropertyChanged 添加到 Item 类。添加了一个按钮来更新最后一项的标签。按下按钮后什么也没发生。所以我添加了另一个内容控件并将其绑定到标签值。按下按钮时,内容控件确实会更新,而汉堡菜单似乎忽略了它。这与我在尝试使用问题中提到的标准 x:Bind 时看到的问题相同。其他控件会更新,但汉堡菜单不会。
    • mm8,删除了我的原始评论,因为被叫走了,所以 5 分钟后锁定评论编辑。我在示例中使用的代码就像在单击按钮时更新标签一样简单。 ((ViewModel)this.DataContext).Items[2].Label = "已登录";内容控件显示更改,但菜单仍显示“3”
    • 从头开始,我需要将 Mode=TwoWay 添加到 DataTemplate 中的 TextBlock 绑定中,一旦我这样做了,它就会在按下按钮时更新。因此,您的答案有效,但需要对完整解决方案进行一些修改。模式=双向。将“模型”类更改为“项目”。将模板的 DataType 更改为“项目”。将 INotifyPropertyChanged 接口添加到 Item 类。那我们就可以走了:D
    【解决方案2】:

    所以mm8提供的解决方案确实有效。 然而,在让它发挥作用的过程中,我发现了如何在不付出任何额外努力的情况下解决最初的问题。 将 Mode=TwoWay(OneWay 也适用)添加到 DataTemplate 中的 TextBlock 绑定解决了在属性更改时获取标签以更新的问题。 然后我发现 HamburgerMenuGlyphItem 本身的数据绑定也需要这个“模式”值设置。一旦我将模式添加到该绑定以及标签在用户登录时开始更新并且根本不需要任何外部代码:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-20
      • 2019-11-09
      • 2018-02-25
      • 2017-12-17
      • 2019-03-17
      • 2023-03-11
      • 1970-01-01
      • 2020-03-10
      相关资源
      最近更新 更多