如何打开和关闭ListView项目的点击事件,打开和关闭列表视图的项目模板中的复选框

时间:2015-11-05 20:00:06

标签: listview checkbox user-controls uwp

我在用户控件中有一个带有XAML列表视图的UWP应用程序,如下所示。

<ListView x:Name="lvDevices"
          Margin="12,8,0,0"
          Grid.Row="4"
          HorizontalContentAlignment="Stretch"
          ItemTemplate="{StaticResource DeviceTemplate}"
          Width="Auto"
          ItemsSource="{Binding Devices}"
          IsItemClickEnabled="True"
          ItemClick="lvDevices_ItemClick"
          d:DataContext="{d:DesignData /SampleData/DevicesVMSampleData.xaml}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

列表视图的项目模板如下。您可以看到项模板有一个复选框,它使用双向绑定绑定到我的视图模型。

<DataTemplate x:Key="DeviceTemplate">
        <Grid Margin="0" HorizontalAlignment="Stretch" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <CheckBox x:Name="chkSelected" IsChecked="{Binding Selected, Mode=TwoWay}" MinWidth="32" Grid.Column="0" Checked="chkSelected_Changed" Unchecked="chkSelected_Changed" />
            <StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0">
                <TextBlock Text="{Binding DeviceName}" Style="{StaticResource TitleTextBlockStyle}" Tag="{Binding ID}" TextWrapping="Wrap" MaxWidth="500"/>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="User:" Margin="0,0,10,0" Style="{StaticResource CaptionTextBlockStyle}" FontWeight="Bold" />
                    <TextBlock Text="{Binding User}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
                </StackPanel>
            </StackPanel>
            <Button x:Name="btnInfo" Grid.Column="2" Background="Transparent" HorizontalAlignment="Right">
                <Image x:Name="imgInfo" HorizontalAlignment="Right" VerticalAlignment="Center" Source="/Assets/InfoIcon-100.png" Height="50" Width="50" />
            </Button>
        </Grid>
    </DataTemplate>

listview的datacontext设置为我的视图模型。

ucDeviceInfo.DataContext = iobj_DevicesViewModel;

所以我想要的是当用户点击列表视图中的anitem时,该项目的复选框会以复选标记更新或删除其复选标记。我认为最好的方法是设置“选定的”#39;当用户单击该行时,ViewModel中的属性为true或false,然后通知视图该属性已更改。 (项目列表是一个可观察的集合。)。

我尝试以下列方式完成此任务:

在UserControl中 - 当用户点击一行时,我使用以下代码在基页中调用一个方法:

private void lvDevices_ItemClick(object sender, ItemClickEventArgs e)
    {
        StartPage lobj_ParentForm;         

        lobj_ParentForm = ((StartPage)((Frame)Window.Current.Content).Content);
        lobj_ParentForm.SendNotifyPropertyChanged( ((Device)e.ClickedItem).ID);
    }

在基页中,我使用以下代码在我的ViewModel中调用方法:

public void SendNotifyPropertyChanged(int pi_DeviceID)
    {
        iobj_DevicesViewModel.DeviceSelectedInListView(pi_DeviceID);
    }

然后在视图模型中,我更新设备的selected属性,并使用以下代码调用notify属性更改函数:

public void DeviceSelectedInListView(int pi_DeviceID)
    {
        Device lobj_SelectedDevice;

        lobj_SelectedDevice = (from lobj_Device in Devices
                       where lobj_Device.ID == pi_DeviceID
                       select lobj_Device).ToList<Device>()[0];


        lobj_SelectedDevice.Selected = !lobj_SelectedDevice.Selected;
        NotifyPropertyChanged("Devices");
        SelectionsChanged();
    }

    public void SelectionsChanged()
    {
        NotifyPropertyChanged("SelectedDeviceCount");
    }

挑战在于,当我执行此操作并调用notify属性更改方法时,我刚刚单击的listview中项目的复选框不会更新。当用户点击列表视图中的某行时,我知道如何让复选框正确更新?

说明此问题的示例项目的链接是 Example Code

1 个答案:

答案 0 :(得分:1)

至于你的代码 - 你几乎做得对。您的收藏参考Devices没有变化,因此绑定不会更新整个集合,您也不会添加/删除元素,因此ObservableCollection可能已更新。在这种情况下,您需要在item的类上调用属性更改。要做到这一点,只需在Device类中实现 INotifyPropertyChanged

public class Device : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    private bool selected;
    public bool Selected
    {
        get { return selected; }
        set { selected = value; RaiseProperty(nameof(Selected)); }
    }
    // rest of the class

在此之后,每当项目内部发生变化时,您也不需要致电NotifyPropertyChanged("Devices");,绑定将完成工作。由于你有 ObservableCollection ,我认为你根本不需要打电话。

The modified sample you have shared

我不太清楚为什么你不使用默认的ListView复选框。如果您将选择模式设置为 Multiple ,那么您将在每个项目中看到一个复选框。如果您想要处理更多操作,可以订阅 SelectionChanged 事件。带有标准复选框的示例ListView:

<ListView Name="myList" SelectionChanged="myList_SelectionChanged" SelectionMode="Multiple">
    <ListView.Items>
        <TextBlock Text="First item"/>
        <TextBlock Text="Second item"/>
        <TextBlock Text="Third item"/>
        <TextBlock Text="Fifth item"/>
    </ListView.Items>
</ListView>

在您的代码中,我很难说出错,因为我看不到您的商品类,我不知道您是否拥有 Selected 属性,是否实施 INotifyPropertyChanged 以及更多小事。