【问题标题】:Get Index of Item in Listview From Button in Item从项目中的按钮获取列表视图中项目的索引
【发布时间】:2015-08-31 18:46:53
【问题描述】:

我正在编写一个通用应用程序,我希望它使用新的“汉堡”样式菜单。为了填充我为应用程序创建的汉堡菜单,我使用了当前托管在 Azure 上的 JSON 数据源。我可以很好地下载数据,将其放在 ObservableCollection 中,然后绑定它——但我需要汉堡菜单中的按钮来知道单击时它所在的列表视图的位置(索引)。

我正在使用绑定到 ListView 的 RelayCommand 来处理其按钮单击操作。

我的页面的 XAML

x:Class="IOTLightsUniversal.MainPage"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IOTLightsUniversal"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
RequestedTheme="Dark"
Name="MPage">
<Page.Resources>
    <MenuFlyout x:Key="FlyoutBase1"/>
</Page.Resources>

<SplitView x:Name="MainSplitView" DisplayMode="CompactOverlay" IsPaneOpen="False" CompactPaneLength="50" OpenPaneLength="225">
    <SplitView.Pane>
        <StackPanel Background="Gray" Name="Root">
            <Button x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Content="&#xE700;"
                 Width="50" Height="50" Background="Transparent" Command="{Binding HamburgerListItemCommand}" Click="HamburgerButton_Click"/>
            <ListView  Padding="-12,0,0,0"  x:Name="HamburgerList" Foreground="White" SelectionChanged="HamburgerList_SelectionChanged">
                <ListView.ItemTemplate>
                    <DataTemplate x:Name="HamburgerItemTemplate">
                        <StackPanel Orientation="Horizontal" Padding="0">
                            <Button Margin="-0,0,0,0"  FontFamily="Segoe MDL2 Assets" Command="{Binding ElementName=Root, Path=DataContext.HamburgerListItemCommand}" Content="&#xE1D6;"  Width="50" Height="50" Background="Transparent" x:Name="HamburgerButton" />
                            <TextBlock x:Name="HamburgerText" Text="{Binding DeviceName}" FontSize="18" Foreground="Black" VerticalAlignment="Center" />
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackPanel>
    </SplitView.Pane>
    <SplitView.Content>
        <Grid>
            <TextBlock Text="SplitView Content" FontSize="54" Foreground="Black"
                       HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <TextBlock Text="&#xE895;" FontFamily="Segoe MDL2 Assets" Foreground="Black" FontSize="54"/>
        </Grid>
    </SplitView.Content>
</SplitView>

我的页面的 .xaml.cs 代码隐藏

    public sealed partial class MainPage : Page
{
    private NavigationHelper navigationHelper;
    public ObservableCollection<AzureDataItem> DefaultViewModel = new ObservableCollection<AzureDataItem>();

    public MainPage()
    {
        this.InitializeComponent();
        HamburgerListItemCommand = new RelayCommand(HamburgerListButtonClick); //new RelayCommand(this.HamburgerListButtonClick);
    }


    public MainPage(Frame frame)
    {
        this.InitializeComponent();
        MainSplitView.Content = frame;
        (MainSplitView.Content as Frame).Navigate(typeof(MicPage));
        getData();
        HamburgerListItemCommand = new RelayCommand(this.HamburgerListButtonClick);
        HamburgerList.ItemsSource = DefaultViewModel;

    }

    private async void getData()
    {
        var AzureDataItems = await AzureDataSource.GetDataItemsAsync();
        foreach (AzureDataItem adi in AzureDataItems)
        {
            DefaultViewModel.Add(adi);
        }
    }

    private void HamburgerButton_Click(object sender, RoutedEventArgs e)
    {
        MainSplitView.IsPaneOpen = !MainSplitView.IsPaneOpen;

    }

    private void HamburgerListButtonClick()
    {
        /*What should I put here?*/
    }

    public ICommand HamburgerListItemCommand
    {
        get;
        private set;
    }

}

到目前为止,我在这里尝试了第二个代码 sn-p:In a ListView containing Buttons, how to get Index of the clicked one?,但是 .Parent 调用获取了按钮的父 StackPanel 而不是 ListView,所以它不起作用。

提前感谢任何解决方案/建议!

【问题讨论】:

    标签: c# windows-runtime winrt-xaml win-universal-app


    【解决方案1】:

    您可以使用“参数化”命令并为按钮指定 CommandParameter 属性。

    <Button Margin="-0,0,0,0"
            FontFamily="Segoe MDL2 Assets"
            Command="{Binding ElementName=Root, Path=DataContext.HamburgerListItemCommand}" 
            CommandParameter="{Binding}"
            Content="&#xE1D6;"
            Width="50"
            Height="50"
            Background="Transparent"
            x:Name="HamburgerButton" />
    

    如您所见,我已将 CommandParameter 属性绑定到当前 DataContext。

    在你的主类中:

    public MainPage() {
        this.InitializeComponent();
        HamburgerListItemCommand = new Command<object>(HamburgerListButtonClick); 
    }
    
    private void HamburgerListButtonClick(object parameter) {
        AzureDataItem item = parameter as AzureDataItem;
        // Now you have access to the clicked item
        int index = DefaultViewModel.IndexOf(item);
    }
    

    如您所见,我使用了一个 Command 类,因为我无法访问您使用的 RelyCommand 的源代码,如果它接受参数,现在也无法访问。下面是 Command 类的源代码:

     class Command : ICommand {
        public event EventHandler CanExecuteChanged;
    
        private Action action;
        private bool canExecute = true;
        public Command(Action action, bool canExecute = true) {
            if (action == null) {
                throw new ArgumentNullException("action");
            }
            this.action = action;
            this.canExecute = canExecute;
        }
        internal bool CanExecuteInternal {
            get {
                return this.canExecute;
            }
            set {
                if (this.canExecute != value) {
                    this.canExecute = value;
                    this.OnCanExecuteChanged(EventArgs.Empty);
                }
            }
        }
        public bool CanExecute(object parameter) {
            return this.canExecute;
        }
        public void Execute(object parameter) {
            this.action();
        }
        private void OnCanExecuteChanged(EventArgs e) {
           if (this.CanExecuteChanged != null) {
                this.CanExecuteChanged(this, e);
            }
        }
    }
    class Command<T> : ICommand {
        public event EventHandler CanExecuteChanged;
    
        private Action<T> action;
        private bool canExecute = true;
        public Command(Action<T> action, bool canExecute = true) {
            if (action == null) {
                throw new ArgumentNullException("action");
            }
            this.action = action;
            this.canExecute = canExecute;
        }
        internal bool CanExecuteInternal {
            get {
                return this.canExecute;
            }
            set {
                if (this.canExecute != value) {
                    this.canExecute = value;
                    this.OnCanExecuteChanged(EventArgs.Empty);
                }
            }
        }
        public bool CanExecute(object parameter) {
            return this.canExecute;
        }
        public void Execute(object parameter) {
            this.action((T)parameter);
        }
        private void OnCanExecuteChanged(EventArgs e) {
            if (this.CanExecuteChanged != null) {
                this.CanExecuteChanged(this, e);
            }
        }
    }
    

    【讨论】:

    • 谢谢,效果很好!命令类最终是必要的,我的实现实际上不包括参数支持。
    猜你喜欢
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多