C# XAML UWP - MenuFlyoutItem列表在MenuFlyoutSubItem中更新不一致

pb3s4cty  于 2022-12-16  发布在  C#
关注(0)|答案(1)|浏览(171)

这可能是一个简单的解决方案-只是解释起来有点长。
我在运行时将自定义列表视图项添加到ListView。每个ListView项都有一个Name,一个布尔值和一个按钮。单击按钮时会显示一个弹出菜单,其中包含子项菜单,如图所示。子项菜单应该只显示所有其他项的名称,而不显示其本身。正确的行为如第一张图中的“项4”所示单击菜单按钮后,我们只能看到子菜单中列出的项目0到3。

问题是,如果我导航到一个子菜单,然后在列表框中添加新项目,则新项目永远不会出现在以前导航到的旧项目的子菜单中。就像下图中一样,我单击了“项目1”按钮,但只列出了项目0和项目2,由于某种原因,项目3和项目4没有列出。

首先,有一个完整的最低VS 2019解决方案演示了行为我在上面描述了GitHub here,但我已经总结了我认为是代码的关键位如下。

非锅炉板XAML标题(MainPage.Xaml)

xmlns:local="using:DynamicFlyoutMenuTest.ViewModels"

主ListView定义及其DataTemplate以及用于在运行时添加ListView项的按钮:

<StackPanel>
    <Button Name="AddCustomListItemBtn" Click="AddCustomListItemBtn_Click">Add Custom ListItem</Button>
    <ListView
        Name="LayerListBox"
        Height="Auto"
        BorderBrush="{ThemeResource SystemBaseLowColor}"
        BorderThickness="1.0"
        ItemsSource="{x:Bind ViewModel.MyCustomListItems}">
        <ListView.HeaderTemplate>
            <DataTemplate>
                <Grid Padding="2" Background="{ThemeResource SystemBaseLowColor}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="190" />
                        <ColumnDefinition Width="132" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Style="{ThemeResource CaptionTextBlockStyle}" Text="Name" />
                    <TextBlock
                        Grid.Column="1"
                        Style="{ThemeResource CaptionTextBlockStyle}"
                        Text="Active" />
                </Grid>
            </DataTemplate>
        </ListView.HeaderTemplate>
        <ListView.ItemTemplate>
            <DataTemplate x:Name="TableDataTemplate" x:DataType="local:MyCustomListItem">
                <Grid Height="48" AutomationProperties.Name="{x:Bind ItemName}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="190" />
                        <ColumnDefinition Width="132" />
                        <ColumnDefinition Width="132" />
                    </Grid.ColumnDefinitions>
                    <TextBlock
                        Grid.Column="0"
                        Padding="10"
                        VerticalAlignment="Center"
                        Text="{x:Bind ItemName, Mode=OneWay}" />
                    <CheckBox
                        Grid.Column="1"
                        VerticalAlignment="Center"
                        IsChecked="{x:Bind isEditing, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                    <Button
                        Name="exportLayerButton"
                        Grid.Column="2"
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Center">
                        <Button.Flyout>
                            <MenuFlyout Opening="MenuFlyout_Opening">
                                <MenuFlyoutItem
                                    Name="Action1Btn"
                                    Click="Action1Btn_Click"
                                    Text="Action 1" />
                                <MenuFlyoutItem
                                    Name="Action2Btn"
                                    Click="Action2Btn_Click"
                                    Text="Action 2" />
                                <MenuFlyoutSubItem x:Name="SubActionsBtn" Text="Choose Sub Action">
                                    <MenuFlyoutItem Name="NoSubActionBtn" Text="None" />
                                </MenuFlyoutSubItem>
                            </MenuFlyout>
                        </Button.Flyout>
                        <Polygon
                            Fill="Black"
                            Points="0,0 6,4,0,8"
                            Stroke="Black" />
                    </Button>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

MainPage.xaml.cs -将项目添加到列表和更新弹出子菜单项

private void MenuFlyout_Opening(object sender, object e)
{
    //make MenuFlyoutSubItem list all Items in ListView except the one triggering  this function
    var menuFlyout = sender as MenuFlyout;
    // get the menu list we want to add to

    MenuFlyoutSubItem menuSubItems = menuFlyout.Items.Where(x => x.Name == "SubActionsBtn").FirstOrDefault() as MenuFlyoutSubItem;

    // get the active maplayerlistitem (that triggered this menu opening event) 
    MyCustomListItem myCustomListItem = (menuFlyout.Target as Button).DataContext as MyCustomListItem;

    menuSubItems.Items.Clear();
    foreach (var targetItem in ViewModel.MyCustomListItems)
    {
        if (myCustomListItem.ItemName != targetItem.ItemName)
        {
            var tItem = new MenuFlyoutItem();
            tItem.Text = targetItem.ItemName.ToString();
            //tItem.Click += new Windows.UI.Xaml.RoutedEventHandler(DoSomethingBtn_Click);
            menuSubItems.Items.Add(tItem);
        }
    }
}

private void AddCustomListItemBtn_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    // Update ListView
    var newItem = new MyCustomListItem();
    newItem.ItemName = "Item " + ViewModel.MyCustomListItems.Count.ToString();
    newItem.isEditing = false;
    ViewModel.MyCustomListItems.Add(newItem);
}

MainViewModel.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Microsoft.Toolkit.Mvvm.ComponentModel;

namespace DynamicFlyoutMenuTest.ViewModels
{
    public class MainViewModel : ObservableObject
    {
        public ObservableCollection<MyCustomListItem> MyCustomListItems = new ObservableCollection<MyCustomListItem>();
        public MainViewModel()
        {

        }
    }
    public class MyCustomListItem : INotifyPropertyChanged
    {
        public MyCustomListItem()
        {

        }

        private bool _isEditing;
        public bool isEditing
        {
            get { return _isEditing; }
            set
            {
                _isEditing = value;
                NotifyPropertyChanged(this, "isEditing");
            }
        }

        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set
            {
                _itemName = value;
                NotifyPropertyChanged(this, "ItemName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void NotifyPropertyChanged(object sender, string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(sender, e);
            }
        }
    }
}

EDIT您可以在https://www.youtube.com/watch?v=yPNNtsS-n5Q查看视频中的问题您可以通过以下方式从GitHub源代码重现该问题

1.使用“添加......”按钮向列表视图添加3个项目。
1.导航到每个ListViewItem的子菜单弹出型按钮
1.使用“添加...”按钮再添加2个列表视图项目
1.导航到两个新项目的子菜单弹出按钮,最后
1.导航到原始3个项目的子菜单Flyout,看到它们没有更新以反映添加的附加ListView项目。

dba5bblo

dba5bblo1#

我找到了一个变通方法,删除了现有的MenuFlyoutSubItem,并在每次打开Flyout时添加一个新的。所以这不是很理想,但确实有效。
如果有人有一个实际的解决方案,我很乐意标记为这样。
否则,解决方法如下:

private void MenuFlyout_Opening(object sender, object e)
        {
            //make MenuFlyoutSubItem list all Items in ListView except the one triggering this function
            var menuFlyout = sender as MenuFlyout;
            // get the menu list we want to add to

            MenuFlyoutSubItem menuSubItems = menuFlyout.Items.Where(x => x.Name == "SubActionsBtn").FirstOrDefault() as MenuFlyoutSubItem;

            // get the active maplayerlistitem (that triggered this menu opening event) 
            MyCustomListItem myCustomListItem = (menuFlyout.Target as Button).DataContext as MyCustomListItem;

            menuFlyout.Items.Remove(menuSubItems);
            menuSubItems = new MenuFlyoutSubItem();
            menuSubItems.Name = "SubActionsBtn";
            menuSubItems.Text = "Choose Sub Action";
            foreach (var targetItem in ViewModel.MyCustomListItems)
             {
                if (myCustomListItem.ItemName != targetItem.ItemName)
                {
                    var tItem = new MenuFlyoutItem();
                    tItem.Text = targetItem.ItemName.ToString();
                    //tItem.Click += new Windows.UI.Xaml.RoutedEventHandler(DoSomethingBtn_Click);
                    menuSubItems.Items.Add(tItem);              
                }
            }
            menuFlyout.Items.Add(menuSubItems);
        }

相关问题