【问题标题】:ListView ItemClick with MVVMListView ItemClick 与 MVVM
【发布时间】:2017-03-11 21:02:19
【问题描述】:

我是 MVVM 新手,有一些我不明白的地方。我到目前为止的代码:

在 ItemListPage.xaml 中:

<ListView ItemsSource="{Binding itemList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          SelectedItem="{Binding itemSelected, Mode=TwoWay}"
          ItemClick="{x:Bind ViewModel.ClickItemList}">

在 ItemListViewModel.cs 中:

    private List<Item> _itemList;
    public List<Item> itemList { get { return _itemList; } set { Set(ref _itemList, value); } }
    private Item _itemSelected;
    public Item itemSelected { get { return _itemSelected; } set { Set(ref _itemSelected, value); } }

    public void ClickItemList()
    {
        System.Diagnostics.Debug.WriteLine("Click on itemlist");
        if (itemSelected != null)
        {
            ((App)App.Current)._itemID = itemSelected._ID;
            NavigationService.Navigate(typeof(Views.ShowItem));
        }
    }

我遇到的问题是在我第一次点击一个项目时,调用了函数 ClickItemList 但属性 itemSelected 仍然是空的,所以我需要第二次点击一个项目来实际执行我想做的操作(保存此项目的 ID 并导航到下一页)。我怎样才能改变我的代码来做到这一点?

除了这个问题,我不明白为什么我应该使用2个属性(例如私有属性_itemSelected和公共“假”属性itemSelected),为什么我不能只使用一个?

【问题讨论】:

  • 什么是 ItemClick 属性?这不是标准的 WPF ListView 事件。
  • 我一直使用那个属性。“当列表视图中的项目接收到交互时发生,并且 IsItemClickEnabled 属性为 true。(继承自 ListViewBase)”来源:msdn.microsoft.com/en-us/library/windows/apps/…
  • 哦...你没有提到它是一个通用应用程序:)。标准 WPF 没有。

标签: c# wpf mvvm uwp


【解决方案1】:

我遇到的问题是在我第一次点击一个项目时,调用了函数 ClickItemList 但属性 itemSelected 仍然是空的,所以我需要第二次点击一个项目来实际执行我想做的操作(保存此项目的 ID 并导航到下一页)。我怎样才能改变我的代码来做到这一点?

这是因为 ListView 将在引发 ItemClick 事件之后更新 SelectedItem。。如果您想知道单击了哪个项目,则需要访问事件参数:

public void ClickItemList(object sender, ItemClickEventArgs e)
{
    var clickedItem = (Item)e.ClickedItem;
}

除了这个问题,我不明白为什么我应该使用2个属性(例如私有属性_itemSelected和公共“假”属性itemSelected),为什么我不能只使用一个?

只是为了澄清一些术语:

  • _itemList 是一个私有字段
  • itemList公共财产*。

属性只不过是一个 getter 和 setter 函数。字段实际上将对象存储在类的实例中。出于这个原因,公共属性通常会有一个私有的支持字段,它可以委托访问。

itemList 必须是公共属性才能绑定到它(通过{Binding})。如果您希望能够在运行时将itemList 更改为全新的列表并让ListView 自动更新其项目,那么您的视图模型必须实现INotifyPropertyChanged 并在itemList 更改时引发PropertyChanged 事件。这就是您的属性的设置器中发生的事情(感谢您拥有的帮助器 Set 方法)。在这种情况下,您需要有一个私有字段来存储实际列表,并使用公共属性确保在您更改 itemList 时引发 PropertyChanged。

双向绑定 ItemsSource 没有意义(就像您一样),因为 ListView 从不更改 ItemsSource。事实上,如果你根本不改变itemList,那么你可以像这样改变你的视图模型**:

// Generates a hidden private field automatically, and is used as if it were a public field
public List<Item> itemList { get; set; }

和这样的 XAML:

<ListView ItemsSource="{x:Bind ViewModel.itemList}" ItemClick="{x:Bind ViewModel.ClickItemList}">

* 我建议遵循 Microsoft 的约定,以大写字母开头命名公共属性,例如 ItemList 而不是 itemList

** x:Bind 也支持绑定到公共字段,而不仅仅是属性,但我建议始终在类的公共接口中使用属性,但这取决于你。

【讨论】:

  • "如果您想知道点击了哪个项目,您需要访问事件参数" => 这正是我的问题,我无法在 ViewModel 中访问事件参数。跨度>
  • 是的,您可以,只需将这 2 个参数精确地添加到您的方法中。这有点破坏 MVVM,如果你想成为一个纯粹主义者,那么在代码隐藏 (.xaml.cs) 中处理事件并在你的 VM 上调用一些东西。
  • 好吧,看起来它现在可以工作了(通过像你说的那样将这 2 个参数添加到方法中),这很奇怪,因为我在 2 天前尝试了完全相同的事情,但它没有工作,在这之间还有像“10个字符串不能转换成长度”这样完全随机出现和消失的XAML错误,感觉有点失落……
【解决方案2】:

感谢您的所有回答,这有助于我更好地理解问题和 MVVM 模式。

我在这里找到的简单解决方案是在我的 .xaml 中将触发事件 ItemClick 更改为 SelectionChanged,因为在 ListView 更新 SelectedItem 之前引发了 ItemClick 事件,但 SelectionChanged 事件随即引发。

现在它按预期工作:单击我的列表框的一个项目 => 更新 SelectedItem 绑定属性 => 触发 SelectionChanged 事件 => 调用我的函数 ClickItemList 并在保存所选项目的 ID 后转到下一页

【讨论】:

  • 这会中断使用键盘更改所选项目,因为一旦更改所选项目(通过任何方式),您就会导航到新页面。这使您的应用程序现在更难访问,因为人们无法使用键盘来导航您的 UI。只是需要考虑的事情。
【解决方案3】:

有时私有属性不是必需的,它们的大部分用途是:

  • 当您需要在“返回”或赋值之前进行一些处理时。

  • 当您需要或想要缓存或延迟加载属性时

  • 当属性不供公众访问时(冗余)

因此,要回答您的问题,如果您的公共财产只是封装它,则不需要私有字段。举个例子。

private string _property;
public string Property {
    get { return _property; }
    set { _property = value; }
}

可以替换为:

public string Property { get; set; }

【讨论】:

  • 首先,感谢您的回答。我所有的 List 都来自对 API Rest 的请求,所以我猜它与第一个用例匹配。但是我仍然不确定为什么在这种情况下需要私有财产,您是否有任何文档链接或有关此的更多信息?我完全不知道在谷歌上搜索什么..
【解决方案4】:

其他两个答案都是正确的,但具体来说,您第一次单击时没有任何反应的原因是因为没有更改选择。
为了解决这个问题,当您打开页面时(例如在构造函数中),您可以将SelectedItem 设置为itemList 的第一项,然后您的第一项应该可以工作。

【讨论】:

  • 那么在 OnClick 中它仍然是错误的(旧)项目。
猜你喜欢
  • 2013-10-28
  • 1970-01-01
  • 2018-12-27
  • 2017-10-11
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多