在 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=""
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);
}
我正在处理具有 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=""
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);
}