【问题标题】:How can I bind the click event in ItemsControl of UWP?如何在 UWP 的 ItemsControl 中绑定点击事件?
【发布时间】:2017-08-08 16:13:50
【问题描述】:

我想做一个 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等属性。唯一的问题是我要绑定的点击事件 Button,但我不知道如何绑定它。

我尝试使用delegate绑定click事件,但没有成功,报错。

你能帮帮我吗?

谢谢

【问题讨论】:

    标签: uwp uwp-xaml


    【解决方案1】:

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

    由于您在模板中使用了Button,因此您可以在NavItems 中创建ClickCommandICommand 类型)并将ButtonCommand 属性绑定到它。

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

    互联网上有大量资源,您可以在其中找到ICommand 实现,看看UWP Toolkit 中它是如何完成的。


    旁注

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

    【讨论】:

    • 我是UWP的初学者,非常感谢您对Listview的建议。另外,我同意您对SelectionChanged的看法。谢谢。
    【解决方案2】:

    为了为您注册按钮单击事件,您需要添加并定义 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 
          }
    
     }
    

    【讨论】:

      【解决方案3】:

      我试过用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;
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 2015-07-26
        • 1970-01-01
        • 2012-06-06
        • 2012-05-23
        • 1970-01-01
        相关资源
        最近更新 更多