从项目中的按钮获取Listview中的项目索引

时间:2015-08-31 18:46:54

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

我正在编写通用应用程序,我希望它使用新的“汉堡”风格菜单。要填充我为应用程序创建的汉堡包菜单,我使用的是当前托管在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;
    }

}

到目前为止,我已经尝试了第二个代码片段:In a ListView containing Buttons, how to get Index of the clicked one?,但.Parent调用获取按钮的父StackPanel而不是ListView,因此它不起作用。

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

1 个答案:

答案 0 :(得分:0)

您可以使用&#34;参数化&#34;命令并为按钮指定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);
        }
    }
}