gpt4 book ai didi

c# - 无法在 MVVM UWP 中取消选择 ListView 项

转载 作者:行者123 更新时间:2023-12-03 10:26:30 25 4
gpt4 key购买 nike

我希望能够单击 ListView 项目,然后将我带到适当的页面。但是由于不存在像 ClickedItem 这样的东西与ItemClick一起去,我必须使用 SelectedItem (获取用户点击的对象)和SelectionChanged捕捉它何时发生(因为这是以一种方式设置的,即当用户单击时,他会进行选择,从而触发此操作)。

因为在 MVVM 中我不能使用事件,所以我将事件绑定(bind)到我的 ViewModel 中的方法。

<GridView x:Name="MyGrid" 
ItemsSource="{x:Bind ViewModel.myList, Mode=OneWay}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
IsSwipeEnabled="false"
SelectedItem="{Binding mySelectedItem, Mode=TwoWay}" // Binding makes it easier to bind the whole object
SelectionChanged="{x:Bind ViewModel.SelectioMade}"
>

我在 ViewModel 中填写了我的列表。我正在使用 INotifyPropertyChanged 的​​ Template10 实现。
private MyListItemClass _mySelectedItem;
public MyListItemClass mySelectedItem{
get { return _mySelectedItem; }
set { Set(ref _mySelectedItem, value); }
}

当用户点击一个项目时,这个简单的方法会将我推到下一页。
public void SelectioMade() {
if (_mySelectedItem != null) {
NavigationService.Navigate(typeof(Views.DetailPage), _mySelectedItem.id);
}
}

这行得通。

问题是做出了选择并且它仍然存在。当我点击 DetailPage 上的返回按钮时,我离开时返回此列表,单击的项目仍处于选中状态。因此,再次单击它实际上并没有进行选择并触发 SelectionChanged .

明显的选择似乎只是设置 mySelectedItemnull当我不再需要该值但它不起作用时。
public void SelectioMade() {
if (_mySelectedItem != null) {
NavigationService.Navigate(typeof(Views.DetailPage), _mySelectedItem.id);
mySelectedItem = null;
}
}

我似乎无法将其设置回 null .如果我在 mySelectedItem = null; 上放置一个断点它只是没有做任何事情。它确实触发了 set { Set(ref _mySelectedItem, value); } ,但 View 不会更新。单击的项目都不会被取消选择,我绑定(bind)到 mySelectedItem.id 之一的 TextBlock 也不会被取消选择。属性被更改(或更确切地说是清空)。

我想知道为什么这不起作用以及如何解决它。我的 MVVM 可能并不完美,我还在学习中。虽然它可能并不完美,但我并不是真的在寻找如何正确编写 MVVM 的建议。我想知道为什么这不起作用,因为在我看来,它应该可以正常工作。

最佳答案

似乎 GridView 不喜欢在 SelectionChanged 处理程序中更改 SelectedItem 属性(如果不使用防护,可能会导致无限循环)。您可以改为在该页面的 OnNavigatedTo 处理程序中将 SelectedItem 设置为 null(或任何与此等效的 Template 10)。

此外,您实际上并不需要订阅 SelectionChanged 事件,因为您可以在 mySelectedItem 属性的 setter 中检测到这一点。

但是,我认为通过监听选择更改事件来处理项目点击是错误的,因为可以通过其他方式(例如,向上/向下箭头键或 Tab 键)更改选择。你要做的就是响应一个item点击并获取点击的item,对吧?为此,您可以 x:Bind 将 ItemClick 事件绑定(bind)到 View 模型中的方法:

<GridView ItemClick="{x:Bind ViewModel.ItemClick}" SelectionMode="None" IsItemClickEnabled="True">
public void ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem;
}

如果您对 View 模型中的 ItemClick 方法签名感到不安,那么您可以创建自己的 ItemClick 行为来执行在 View 模型中公开的命令,并将命令的参数绑定(bind)到单击的项目。

如果您出于某种原因没有使用行为,那么您可以创建自己的附加属性,如下所示:
public class ViewHelpers
{
#region ItemClickCommand

public static readonly DependencyProperty ItemClickCommandProperty =
DependencyProperty.RegisterAttached("ItemClickCommand", typeof(ICommand), typeof(ViewHelpers), new PropertyMetadata(null, onItemClickCommandPropertyChanged));

public static void SetItemClickCommand(DependencyObject d, ICommand value)
{
d.SetValue(ItemClickCommandProperty, value);
}

public static ICommand GetItemClickCommand(DependencyObject d)
{
return (ICommand)d.GetValue(ItemClickCommandProperty);
}

static void onItemClickCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var listView = d as ListViewBase;
if (listView == null)
throw new Exception("Dependency object must be a ListViewBase");

listView.ItemClick -= onItemClick;
listView.ItemClick += onItemClick;
}

static void onItemClick(object sender, ItemClickEventArgs e)
{
var listView = sender as ListViewBase;
var command = GetItemClickCommand(listView);
if (command != null && command.CanExecute(e.ClickedItem))
command.Execute(e.ClickedItem);
}

#endregion
}

XAML 不需要使用 MVVM 模式,这意味着您需要自己编写许多“缺失”的功能以使 MVVM 对您更容易(如上面的 ItemClick 附加属性)。也许模板 10 已经为您提供了一些行为?我不熟悉它。

关于c# - 无法在 MVVM UWP 中取消选择 ListView 项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40698963/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com