如何绑定UWP的ItemsControl中的click事件?

时间:2017-08-07 09:01:32

标签: uwp uwp-xaml

我想制作一个HamburgerMenu。这里是XAML。

<SplitView Grid.Row="1" HorizontalAlignment="Left">
                <SplitView.Content>
                    <ListView>
                        <ItemsControl x:Name="NavItemsControl">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel></StackPanel>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Button>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="auto"></ColumnDefinition>
                                                <ColumnDefinition Width="*"></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <TextBlock FontFamily="Segoe MDL2 Assets" Text="{Binding Icon}"></TextBlock>
                                            <TextBlock Text="{Binding Content}" Grid.Column="1"></TextBlock>
                                        </Grid>
                                    </Button>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </ListView>
                </SplitView.Content>
            </SplitView>

这里有代码:

public class NavItems : INotifyPropertyChanged
    {
        string _Icon;
        public string Icon
        {
            set
            {
                _Icon = value;
                OnPropertyChanged("Icon");
            }
            get
            {
                return _Icon;
            }
        }
        string _Content;
        public string Content
        {
            set
            {
                _Content = value;
                OnPropertyChanged("Content");

            }
            get
            {
                return _Content;
            }
        }            

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

在设置了NavItemsControl的ItemSource之后,我可以轻松地绑定诸如Icon或Content之类的属性。唯一的问题是我想绑定click事件  按钮,但我不知道如何绑定它。

我尝试使用委托来绑定click事件,但它不起作用并报告错误。

你能帮我吗?

谢谢

3 个答案:

答案 0 :(得分:4)

在我们回答您的问题之前,让我们先修复您的XAML。您正在使用ListView来换行ItemsControl,这是不必要的。实际上,ListView本身继承自ItemsControl,基本上是它的一个更强大的版本。在您的情况下,ItemsControl就足够了,因此您可以安全地删除ListView包装。

由于您在模板中使用了Button,因此您可以在ClickCommand中创建ICommand(类型为NavItems)并绑定Button' s Command属性。

<Button Command="{Binding ClickCommand}" />

互联网上有大量资源可供您ICommand实施,请查看UWP Toolkit的工作方式。

旁注

我个人不喜欢使用SelectionChanged,因为它是一个可由数据更改触发的数据驱动的事件。这可能是不可预测的并且容易出错。此外,除非您手动重置SelectedIndex,否则无法重新选择相同的项目。按钮Click(或来自ItemClick的{​​{1}})是输入驱动的事件,只能(在大多数情况下)由用户操作调用,很少给你任何副作用。

答案 1 :(得分:1)

要为您注册事件按钮单击,您需要添加并定义ListView的Selection Changed事件。所以你的代码应该是这样的:

<SplitView Grid.Row="1" HorizontalAlignment="Left">
                <SplitView.Content>
                    <ListView x:Name="itemListView" SelectionChanged="ItemListView_SelectionChanged">
                        <ItemsControl x:Name="NavItemsControl">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel></StackPanel>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Button>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="auto"></ColumnDefinition>
                                                <ColumnDefinition Width="*"></ColumnDefinition>
                                            </Grid.ColumnDefinitions>
                                            <TextBlock FontFamily="Segoe MDL2 Assets" Text="{Binding Icon}"></TextBlock>
                                            <TextBlock Text="{Binding Content}" Grid.Column="1"></TextBlock>
                                        </Grid>
                                    </Button>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </ListView>
                </SplitView.Content>
            </SplitView>

C#代码背后应该是这样的:

private void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
      if(itemListView.SelectedItem!=null){
         Debug.WriteLine(itemListView.SelectedIndex + " Index selected");
         // More logic here 
      }

 }

答案 2 :(得分:0)

我尝试用ICommand做,但代码看起来很丑陋。仅供参考。

<SplitView Grid.Row="1" HorizontalAlignment="Left">
                <SplitView.Content>
                    <ItemsControl x:Name="NavItemsControl">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Button Command="{Binding ClickCommand}" Padding="10,20" Background="Transparent">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="auto"></ColumnDefinition>
                                            <ColumnDefinition Width="*"></ColumnDefinition>
                                        </Grid.ColumnDefinitions>
                                        <TextBlock FontFamily="Segoe MDL2 Assets" Text="{Binding Icon}" VerticalAlignment="Center"></TextBlock>
                                        <TextBlock Text="{Binding Content}" Grid.Column="1" VerticalAlignment="Center" Padding="20,0,0,0"></TextBlock>
                                    </Grid>
                                </Button>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </SplitView.Content>
            </SplitView>

代码背后:

public MainPage()
        {
            InitializeComponent();
            NavItems.ClickVoidDelegate CD = new NavItems.ClickVoidDelegate(()=> { Debug.WriteLine("123"); });
            List<NavItems> NavItemsList = new List<NavItems>()
            {
                new NavItems(){
                    Icon="\xE166",Content="Open",ClickCommand=new NavItems.ClickCommandClass(CD)
                }
            };

            NavItemsControl.ItemsSource = NavItemsList;
        }
public class NavItems : INotifyPropertyChanged
        {
            string _Icon;
            public string Icon
            {
                set
                {
                    _Icon = value;
                    OnPropertyChanged("Icon");

                }
                get
                {
                    return _Icon;
                }
            }
            string _Content;
            public string Content
            {
                set
                {
                    _Content = value;
                    OnPropertyChanged("Content");

                }
                get
                {
                    return _Content;
                }
            }
            ClickCommandClass _ClickCommand;
            public ClickCommandClass ClickCommand
            {
                get;
                set;
            }
            public class ClickCommandClass : ICommand
            {
                public ClickCommandClass(ClickVoidDelegate ClickVoid)
                {
                    _ClickVoid = ClickVoid;
                }
                ClickVoidDelegate _ClickVoid;
                public void Execute(object parameter)
                {
                    if (_ClickVoid != null)
                    {
                        _ClickVoid();
                    }
                }
                public bool CanExecute(object parameter)
                {
                    return true;
                }
                public event EventHandler CanExecuteChanged;
            }
            public delegate void ClickVoidDelegate();
            protected virtual void OnPropertyChanged(string propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }