首页 > 解决方案 > WPF ListView - 在未单击所选项目时检测 ListVewItem

问题描述

当用户没有通过单击选择项目但用户点击它时,我试图在 WPF 的 ListView 中获取项目。有没有办法在 WPF ListView 中实现这一点。ListView 数据源由代码隐藏中的动态集合填充。当用户点击它时,我得到一个空对象。

Item selectedItem = (Item)lv_CartItems.SelectedItem;

这就是我的数据模板在列表视图中的样子。

<ListView.ItemTemplate>
                <DataTemplate>

                    <Viewbox>
                        <Grid Width="230" Height="110" >

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width=".1*" />
                                <ColumnDefinition />
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition Width=".5*" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="2*" />
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>

                            <Border BorderBrush="LightGray" BorderThickness="1"
                               Grid.Row="0" Grid.Column="0"
                               Grid.ColumnSpan="6" Grid.RowSpan="3" >
                            </Border>

                            
                            <Viewbox Grid.Row="0" >
                                <Image Name="img_ItemImage" 
                                       Source="{Binding Image, Mode=TwoWay }" 
                                       Width="20" Height=" 25" />
                            </Viewbox>

                            <Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
                                <TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
                                           Text="{Binding Name , Mode=TwoWay }" Tag="{Binding SKU_No,Mode=TwoWay}" >
                                    
                                </TextBlock>
                            </Viewbox>

                            <Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
                                <TextBlock  Foreground="Gray" >Qty:</TextBlock>
                            </Viewbox>

                            <Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
                                <StackPanel Orientation="Horizontal" >
                                    <Button  Name="btn_Minus" FontWeight="ExtraBold"  Padding="0"  Width="12"   
                                         Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
                                        <Image Source="/Resources\Icons\minus.png" ></Image>
                                    </Button>

                                    <Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray"   >
                                        <TextBlock Name="lbl_Quantity"  FontWeight="Bold" Foreground="Gray"
                                               HorizontalAlignment="Center" VerticalAlignment="Center" 
                                               Text="{Binding Quantity , Mode=TwoWay }">
                                        </TextBlock>
                                    </Border>

                                    <Button Name="btn_Increment"  FontWeight="ExtraBold"  Width="12"
                                         Resources="{StaticResource cartitembutton}" 
                                        Padding="0"
                                        Click="btn_Increment_Click">
                                        <Image Source="/Resources\Icons\union_10.png" ></Image>
                                    </Button>

                                </StackPanel>
                            </Viewbox>

                            <Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0" 
                                     HorizontalAlignment="Left" Grid.ColumnSpan="3"  >
                                <TextBlock Name="lbl_Price"  FontWeight="DemiBold"
                                            Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
                            </Viewbox>

                            <Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3" 
                                 VerticalAlignment="Top" Margin="0,0"  >
                                <TextBlock Name="lbl_Appearence" 
                                           Text="{Binding Appearance , Mode=TwoWay }" 
                                           TextWrapping="Wrap" Foreground="Gray" Width="210" >
                                </TextBlock>
                            </Viewbox>

                            <Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
                                >
                                <Button Name="btn_DeleteItem" 
                                        Click="btn_DeleteItem_Click" 
                                        Resources="{StaticResource cartitembutton}" >
                                    <Image Source="/Resources/Icons/delete.png"  ></Image>
                                </Button>
                            </Viewbox>

                        </Grid>
                    </Viewbox>
                </DataTemplate>
                
            </ListView.ItemTemplate>

标签: c#wpfdata-binding

解决方案


您应该使用数据绑定来检索所选项目。源属性将在ListView.SelectedItem更改时自动更新。
触摸的处理方式与单击的处理方式相同。该框架将触摸事件转换为鼠标事件。

我注意到您将每个元素都包装成一个ViewBox. 这不是必需的,只会降低性能。当元素托管在 aGrid中时,默认情况下它们会自动调整大小。例外是需要初始大小的元素,例如Shapeor Image。但由于项目容器不会自行调整大小,因此容器的内容也不会调整大小。

要强制所有元素占据最大水平空间,您可以设置以Style项目容器为目标的 a:

<ListView.ItemContainerStyle>
  <Style TargetType="ListBoxItem">
      <Setter Property="HorizontalContentAlignment" 
              Value="Stretch" />
  </Style>
</ListView.ItemContainerStyle>

主窗口.xaml.cs

public partial class MainWindow : Window
{
  public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
    "Items",
    typeof(ObservableCollection<Item>),
    typeof(MainWindow),
    new PropertyMetadata(default(ObservableCollection<Item>)));

  public ObservableCollection<Item> Items
  {
    get => (ObservableCollection<Item>) GetValue(MainWindow.ItemsProperty);
    set => SetValue(MainWindow.ItemsProperty, value);
  }

  public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
    "SelectedItem",
    typeof(Item),
    typeof(MainWindow),
    new PropertyMetadata(default(Item), MainWindow.OnSelectedItemChanged));

  public Item SelectedItem
  {
    get => (Item) GetValue(MainWindow.SelectedItemProperty);
    set => SetValue(MainWindow.SelectedItemProperty, value);
  }

  public MainWindow()
  {
    InitializeComponent();
    this.DataContext = this;

    this.Items = new ObservableCollection<Item>();

    // Initialize data source
    CreateItems(); 
  }

  // Property changed callback of the SelectedItem property
  private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    // Reference to instance members in a class scope
    var _this = d as MainWindow;

    if (e.NewValue is ItemCollection selectedItem)
    {
      // Handle currently selected item
    }
  }
}

主窗口.xaml

<Window>
  <ListView ItemsSource="{Binding Items}"
            SelectedItem="{Binding SelectedItem}" />
</Window>

推荐阅读