在 ListViewItem 上绑定 IsSelected 在 UWP 应用程序中对我不起作用

Binding IsSelected on ListViewItem not working for me in UWP application

我正在处理具有 Selected 属性 的对象列表,我正在尝试将其绑定到 IsSelected 属性 ListViewItem 在 UWP 中的多 select ListView 控件中。

我似乎无法让绑定生效。 ListView 中的复选框不会呈现选中状态,如果 Selected = True 并且 Selected 上的设置在选中项目时永远不会被触发。

SettingsPage.xaml

<Page.Resources>
    <DataTemplate x:Key="PreviewColumnTemplate" x:DataType="models:Column">
        <TextBlock>
            <Run Text="{x:Bind name}"/>
            <Run Text=" ("/>
            <Run Text="{x:Bind ColumnValidation.column_label}"/>
            <Run Text=") "/>
        </TextBlock>
    </DataTemplate>

    <Style x:Key="previewColumnListViewItem" TargetType="ListViewItem">
        
    </Style>
</Page.Resources>
        
<ListView
    x:Name="previewColumnListView"
    ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"
    ItemTemplate="{StaticResource PreviewColumnTemplate}"
    Height="400"
    SelectionMode="Multiple"
    SelectionChanged="previewColumnListView_SelectionChanged">
    <ListView.Resources>
        <Style TargetType="ListViewItem" BasedOn="{StaticResource previewColumnListViewItem}">
            <Setter Property="IsSelected" Value="{Binding Selected, Mode=TwoWay}"/>
        </Style>
    </ListView.Resources>
</ListView>

ViewModel.CurrentDrillHole.Collar 对象的类型是 Table,看起来像这样:

public class Table : BindableBase
{
    public string Name { get; set; }
    public TableValidation TableValidation { get; set; }
    public List<Column> Columns { get; set; }
    public List<Row> Rows { get; set; } = new List<Row>();
}

Column 对象看起来像这样。在这里我想绑定到 Selected 属性.

public class Column : BindableBase, INotifyPropertyChanged
{
    public string name { get; set; }
    public ColumnValidation ColumnValidation { get; set; }
    public List<RefEntryValue> LookupValues { get; set; } = null;

    private bool _selected = false;

    public bool Selected {
        get => _selected;

        set
        {
            _selected = value;

            OnPropertyChanged();
        }
    }
}

任何我可以尝试的想法都将不胜感激。感谢您的帮助!

当您设置 SelectionMode="Multiple" 时,ListViewItem 使用默认的 ListViewItemTemplate,其键为“ListViewItemExpanded”。

其样式如下:

 <Style TargetType="ListViewItem" x:Key="ListViewItemExpanded">
    ......
    <ControlTemplate TargetType="ListViewItem">
        <Grid x:Name="ContentBorder"
          Control.IsTemplateFocusTarget="True"
          FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
          Background="{TemplateBinding Background}"
          BorderBrush="{TemplateBinding BorderBrush}"
          BorderThickness="{TemplateBinding BorderThickness}"
          CornerRadius="{TemplateBinding CornerRadius}"
          RenderTransformOrigin="0.5,0.5">
            ……
            <Border x:Name="MultiSelectSquare"
                        BorderBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                        BorderThickness="2"
                        Width="20"
                        Height="20"
                        Margin="12,0,0,0"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Left"
                        Visibility="Collapsed">
                <Border.Clip>
                    <RectangleGeometry Rect="0,0,20,20">
                        <RectangleGeometry.Transform>
                            <TranslateTransform x:Name="MultiSelectClipTransform" />
                        </RectangleGeometry.Transform>
                    </RectangleGeometry>
                </Border.Clip>
                <Border.RenderTransform>
                    <TranslateTransform x:Name="MultiSelectCheckBoxTransform" />
                </Border.RenderTransform>
                <FontIcon x:Name="MultiSelectCheck"
                            FontFamily="{ThemeResource SymbolThemeFontFamily}"
                            Glyph="&#xE73E;"
                            FontSize="16"
                            Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                            Visibility="Collapsed"
                            Opacity="0" />
            </Border>
            <Border x:Name="MultiArrangeOverlayTextBorder"
                        Opacity="0"
                        IsHitTestVisible="False"
                        Margin="12,0,0,0"
                        MinWidth="20"
                        Height="20"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Left"
                        Background="{ThemeResource SystemControlBackgroundAccentBrush}"
                        BorderThickness="2"
                        BorderBrush="{ThemeResource SystemControlBackgroundChromeWhiteBrush}">
                <TextBlock x:Name="MultiArrangeOverlayText"
              Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DragItemsCount}"
              Style="{ThemeResource CaptionTextBlockStyle}"
              IsHitTestVisible="False"
              Opacity="0"
              VerticalAlignment="Center"
              HorizontalAlignment="Center"
              AutomationProperties.AccessibilityView="Raw" />
            </Border>

        </Grid>

    </ControlTemplate>
    </Setter.Value>
</Style>

如你所见,它的样式中没有CheckBox,它是由Border和FontIcon组成的。

如果你想解决这个问题,我建议你可以在DataTemplate中添加CheckBox。通过这样做,我们可以将“Selected”绑定到 CheckBox 的“IsChecked”属性。 请参考以下代码。

<ListView
x:Name="previewColumnListView"
ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"   
Height="400"
SelectionChanged="previewColumnListView_SelectionChanged">
    <ListView.ItemTemplate>
        <DataTemplate x:Key="PreviewColumnTemplate" x:DataType="models:Column">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding Selected, Mode=TwoWay}"/>
                <TextBlock>
          <Run Text="{x:Bind name}"/>
          <Run Text=" ("/>
          <Run Text="{x:Bind ColumnValidation.column_label}"/>
          <Run Text=") "/>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

最后的样子是这样的。这对其他人来说看起来很笨重吗?如果 ListView 控件使处理集合和 SelectionMode="Multiple".

变得更容易,那就太好了

SettingsPage.xaml

<ListView
    x:Name="previewColumnListView"
    ItemsSource="{x:Bind ViewModel.CurrentDrillHole.Collar.Columns, Mode=TwoWay}"
    Height="400"
    SelectionChanged="previewColumnListView_SelectionChanged"
    IsItemClickEnabled="True"
    ItemClick="previewColumnListView_ItemClick">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="models:Column">
            <StackPanel Orientation="Horizontal">
                <CheckBox Click="previewColumnListView_CheckBox_Click" IsChecked="{Binding Selected, Mode=TwoWay}"/>
                <TextBlock>
                  <Run Text="{x:Bind name}"/>
                  <Run Text=" ("/>
                  <Run Text="{x:Bind ColumnValidation.column_label}"/>
                  <Run Text=") "/>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

SettingsPage.xaml.cs

private async void previewColumnListView_CheckBox_Click(object sender, RoutedEventArgs e)
{
    // update the list of selected columns
    Settings.CollarPreviewFields = ViewModel.CurrentDrillHole.Collar.Columns.Where(x => x.Selected).Select(x => x.name).ToList();

    await App.SaveSettings();
}

private void previewColumnListView_ItemClick(object sender, ItemClickEventArgs e)
{
    Column selectedColumn = (Column)e.ClickedItem;

    selectedColumn.Selected = !selectedColumn.Selected;

    // trigger checkbox click event. will update the list and save.
    previewColumnListView_CheckBox_Click(null, null);
}