【问题标题】:UWP - MVVM - Remove ListView item using ItemTemplate buttonUWP - MVVM - 使用 ItemTemplate 按钮删除 ListView 项目
【发布时间】:2018-10-10 23:53:51
【问题描述】:

我有一个显示项目列表的屏幕,用户可以单击按钮从列表中删除相应的项目。

我正在尝试使用 MVVM。

但该项目在获取操作时并不知道包含列表。 我在这里和那里看到了一些答案,但没有一个使用我在我的环境中拥有的开箱即用的 MVVM 功能 例如使用 PRISM 的那个(不知道我是否也应该使用它,它是标准的吗?):

这是 XAML:

<ListView ItemsSource="{Binding MyItemList}" SelectionMode="None" ScrollViewer.VerticalScrollMode="Disabled" ItemContainerTransitions="{x:Null}"> 
    <ListView.ItemTemplate>
        <DataTemplate >
            <Grid Grid.Row="1" HorizontalAlignment="Stretch" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" />
                    <ColumnDefinition Width="2*" />
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{Binding ItemClass.Property01, Mode=TwoWay}" />
                <Button Grid.Column="1" Command="{Binding RemoveItemCommand}" >
                    <SymbolIcon Symbol="Cancel" />
                </Button>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这里是 ModelView 列表:

private static ObservableCollection<ItemClass> _MyItemList = new ObservableCollection<ItemClass> {
    new ItemClass{ Property01 = "Sometext" }
};
public ObservableCollection<ItemClass> MyItemList { get { return _MyItemList; } }

并且我希望能够执行以下操作(主模型视图中的代码示例,如果需要解决问题,我可以创建一个项目模型视图):

public IMvxCommand RemoveItemCommand { get; private set; }
public MyViewModel(IUserDialogs dialogs)
{
    RemoveItemCommand = new MvxCommand(RemoveItem);
}
public void RemoveItem(object theItem) { MyItemList.Remove(theItem); }

【问题讨论】:

  • 如果列表项不知道 hte 列表,您有两个选择: 使用路由事件使容器(引用列表)来处理点击 |让项目知道列表。我认为你不需要做任何特别的事情。假设您没有编写代码来重用 ViewModel 实例,一旦 Item 超出范围,它将不会将列表保留在内存中。循环引用在 .NET 中并不少见,但是可能有更好的方法我不知道。

标签: c# listview mvvm uwp listviewitem


【解决方案1】:

x:Name="listView" 属性添加到您的ListView,然后在模板中

<Button Grid.Column="1"
    Command="{Binding ElementName=listView, Path=DataContext.RemoveItemCommand}"
    CommandParameter="{Binding}" >

但是,当我遇到这样的问题时,我通常只使用代码后面。原因是,我可以在 Visual Studio 中对 C# 代码使用调试器,但调试这些复杂的绑定要困难得多。这是一个 C# 版本,代码更简洁,更易于调试:

void removeItem_Click( object sender, RoutedEventArgs e )
{
    object i = ((FrameworkElement)sender).DataContext;
    ( this.DataContext as MyViewModel )?.RemoveItem( i );
}

或者这只是我个人的喜好。

【讨论】:

    【解决方案2】:

    最好在列表视图上有一个上下文菜单项(或页面上某处的删除按钮)来删除当前选定的项目。然后,您可以从列表视图中获取选择。

    或者,您可以将上下文菜单附加到 PrepareContainterForItemOverride 中的列表视图项(并在其他 Override 方法中将其分离)

    那将是一种更标准的交互方式。

    如果您必须在列表视图项中包含按钮,那么获取列表项的最简单方法可能是使用可视化树助手从按钮上升到列表视图项,然后获取实际项来自列表视图项。

    【讨论】:

      【解决方案3】:

      感谢所有提示, 使用 Soonts 的答案,我能够开发出一个快速的解决方案,

      以下是最终实现的样子,供任何想要复制/粘贴/调整的人参考(注意我没有测试代码,因为我替换了变量/函数名称):

      XAML:

      <ListView x:Name="ItemClass_ListView" ItemsSource="{Binding MyItemList}" SelectionMode="None" ScrollViewer.VerticalScrollMode="Disabled" ItemContainerTransitions="{x:Null}"> 
          <ListView.ItemTemplate>
              <DataTemplate >
                  <Grid Grid.Row="1" HorizontalAlignment="Stretch" >
                      <Grid.ColumnDefinitions>
                          <ColumnDefinition Width="2*" />
                          <ColumnDefinition Width="2*" />
                      </Grid.ColumnDefinitions>
                      <TextBox Grid.Column="0" Text="{Binding ItemClass.Property01, Mode=TwoWay}" />
                      <Button Grid.Column="1" Command="{Binding ElementName=ItemClass_ListView, Path=DataContext.RemoveItemCommand}" CommandParameter="{Binding}" >
                          <SymbolIcon Symbol="Cancel" />
                      </Button>
                  </Grid>
              </DataTemplate>
          </ListView.ItemTemplate>
      </ListView>
      

      视图模型:

      public class MyViewModel : BaseViewModel, INotifyPropertyChanged
      {
          public IMvxCommand RemoveItemCommand { get; private set; }
          public MyViewModel()
          {
              // Initializing Commands
              RemoveItemCommand = new MvxCommand<ItemClass>(OnRemoveItemClick);
          }
      
          public void OnRemoveItemClick(ItemClass anItem)
          {
              // Do stuff...
          }
      
          private static ObservableCollection<ItemClass> _MyItemList = new ObservableCollection<ItemClass> {
              new ItemClass(),
              new ItemClass()
          };
      
          public ObservableCollection<ItemClass> MyItemList
          {
              get { return _MyItemList; }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-30
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-09
        • 1970-01-01
        相关资源
        最近更新 更多