c# - ListView ItemClick 与 MVVM

标签 c# wpf mvvm uwp

我是 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 个属性(例如私有(private)属性 _itemSelected 和公共(public)“假”属性 itemSelected),为什么我不能只使用一个?

最佳答案

The problem I have is on my first click on an item, the function ClickItemList is called but the attribute itemSelected is still empty, so I need to click a 2nd time on an item to actually do the action I want to do (save this item's ID and navigate to the next page). How can I change my code to do that ?



这是因为 ListView 将在引发 ItemClick 事件后更新 SelectedItem。如果您想知道单击了哪个项目,则需要访问事件参数:
public void ClickItemList(object sender, ItemClickEventArgs e)
{
    var clickedItem = (Item)e.ClickedItem;
}

Aside from this problem, I don't understand why I should use 2 attributes (for example the private attribute _itemSelected and the public "fake" attribute itemSelected), why can't I use only one ?



只是为了澄清一些术语:
  • _itemList私有(private)领域 .
  • itemList公共(public)属性(property) *。

  • 属性只不过是一个 getter 和 setter 函数。字段实际上将对象存储在类的实例中。出于这个原因,公共(public)属性通常会有一个私有(private)的支持字段,它委托(delegate)访问。
    itemList必须是公共(public)属性才能绑定(bind)到它(通过 {Binding} )。如果您希望能够更改itemList在运行时创建一个全新的列表并让 ListView 自动更新其项目,那么您的 View 模型必须实现 INotifyPropertyChanged 并在 itemList 时引发 PropertyChanged 事件被改变。这就是您的属性的 setter 中发生的事情(感谢您拥有的帮助器 Set 方法)。在这种情况下,您将需要一个私有(private)字段来存储实际列表,并使用公共(public)属性确保在 itemList 时引发 PropertyChanged。由你改变。

    由于 ListView 从不更改 ItemsSource,因此双向绑定(bind) ItemsSource 没有意义(正如您所拥有的)。事实上,如果你从不改变 itemList完全可以,然后您可以像这样更改您的 View 模型**:
    // 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 的约定,以大写字母开头命名公共(public)属性,例如 ItemList而不是 itemList .

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

    关于c# - ListView ItemClick 与 MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40314065/

    相关文章:

    mvvm - 如何导航到扩展抽象类的 ViewModel?

    c# - 在 MVVM 中实现临时覆盖的最佳方式

    c# - 如何使 "new ASCIIEncoding().GetBytes(usernamePassword)"读取 "§"符号

    java - 逆正态累积分布函数转换

    css - 如何添加wpf图像按钮?

    c# - WPF : How to change the MouseOver/Selected background colour of a GridView row

    c# - 如何使用 MVVM 更新 ContextMenu 的 ItemSource

    c# - 多个上下文实例化上的 EntityFramework 事务

    c# - 为什么异步调用后调试器不在断点处停止?

    c# - IDataErrorInfo - 它是如何工作的