Я работаю со списком объектов, у которых есть свойство Selected
, и пытаюсь связать его со свойством IsSelected
на ListViewItem
в элементе управления с множественным выбором ListView
в UWP.
Я просто не могу заставить привязку работать. Флажки в ListView
не отображаются отмеченными, если Selected = True
и Set on Selected
никогда не срабатывают при проверке элемента.
НастройкиPage.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.
Если вы хотите решить эту проблему, я предлагаю вам добавить CheckBox в DataTemplate. Делая это, мы можем привязать «Выбрано» к свойству «Проверено» флажка. Пожалуйста, обратитесь к следующему коду.
<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"
.
НастройкиPage.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>
НастройкиPage.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);
}
Это действительно ответ. НастройкиPage.xaml