2017-02-14 6 views
2

У меня есть представление списка с сеткой, которая имеет два столбца. Первый столбец содержит флажки, привязанные к выбранному свойству listviewitem, а второй столбец - текст. В заголовке для столбца флажков у меня есть флажок, который я хочу использовать как кнопку выбора/отмены выбора. Я использовал datatriggers для этого, но он работает только тогда, когда я удаляю привязку между флажками и выбранным свойством. Должен ли я использовать триггер данных для установки связанного свойства?Установите флажок Multiselect Listview with select all. Datatrigger on binded property

Screenshot

отделенного кода

namespace ListviewWCheckboxes 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     List<string> listItems = new List<string>() { "foo", "bar", "blah" }; 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void Window_Loaded(object sender, RoutedEventArgs e) 
     { 
      pdflistView.ItemsSource = listItems; 
     } 
    } 
} 

XAML

<Window x:Class="ListviewWCheckboxes.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:ListviewWCheckboxes" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" 
     Loaded="Window_Loaded"> 
    <Grid> 
     <ListView x:Name="pdflistView" HorizontalAlignment="Left" Height="300" Margin="5" VerticalAlignment="Top" Width="240" 
         SelectionMode="Extended" 
         > 
      <ListView.View> 
       <GridView> 
        <GridViewColumn> 
         <GridViewColumn.Header> 
          <CheckBox x:Name="ckbxSelectAll"/> 
         </GridViewColumn.Header> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <CheckBox IsChecked="{Binding Path=IsSelected, 
               RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}, Mode=FindAncestor},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> 
            <CheckBox.Style> 
             <Style TargetType="CheckBox"> 
              <Style.Triggers> 
               <DataTrigger Binding="{Binding ElementName=ckbxSelectAll, Path=IsChecked}" Value="True"> 
                <Setter Property="IsChecked" Value="True" /> 
               </DataTrigger> 
               <DataTrigger Binding="{Binding ElementName=ckbxSelectAll, Path=IsChecked}" Value="False"> 
                <Setter Property="IsChecked" Value="False" /> 
               </DataTrigger> 
              </Style.Triggers> 
             </Style> 
            </CheckBox.Style> 

           </CheckBox> 
           <DataTemplate.Triggers> 

           </DataTemplate.Triggers> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 

        </GridViewColumn> 
        <GridViewColumn Header="Pdf" DisplayMemberBinding="{Binding}"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

ответ

0

Я считаю, что лучший способ осуществить это создать свойство 'IsSelected' на классе и сковал, что с флажком (IsChecked) и listview (isSelected). Возьмите флажок отмеченного события заголовка и вручную переключите свойство IsSelected элементов в коллекции, чтобы обновить флажок и listviewitems. Пожалуйста, дайте мне знать, если у вас есть другие вопросы.

+0

Это работает до тех пор, пока я не использую флажки, чтобы выбрать строку перед использованием кнопки selectall. Если я выберу пункт foo с помощью флажка, то отмените его выбор, а флажок «Выбрать все» foo не будет выбран, а остальные будут отображаться. каждый элемент разбивается, если они выбраны вручную. Любая идея о том, как это исправить? –

+0

@WIllCruz Да, я вижу, что он нарушает выбор; жаль, что я ответил слишком рано. Я обновил сообщение. – AjS

2

Используя предложение AjS, я придумал это решение.

Я также смог придумать решение, которое просверлило визуальное дерево списка, пока я не получил VirtualizingStackPanel, который содержит все элементы ListviewItems и не прокрутит их, задав свойство IsSelected, но это кажется более чистым.

XAML

<Window x:Class="ListviewWCheckboxes.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:ListviewWCheckboxes" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <ListView x:Name="pdflistView" HorizontalAlignment="Left" Height="300" Margin="5" VerticalAlignment="Top" Width="240" 
         SelectionMode="Extended" ItemsSource="{Binding Path=listItems}"> 
      <ListView.ItemContainerStyle> 
       <Style TargetType="ListViewItem"> 
        <Setter Property="IsSelected" Value="{Binding is_Selected}"/> 
       </Style> 
      </ListView.ItemContainerStyle> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn> 
         <GridViewColumn.Header> 
          <CheckBox x:Name="ckbxSelectAll" Checked="ckbxSelectAll_Checked" Unchecked="ckbxSelectAll_Checked"/> 
         </GridViewColumn.Header> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <CheckBox IsChecked="{Binding is_Selected}"/> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Header="Pdf" DisplayMemberBinding="{Binding Path=text}"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

код

using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows; 
using System.Windows.Controls; 

namespace ListviewWCheckboxes 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public ObservableCollection<someobjects> listItems { get; set; } = new ObservableCollection<someobjects>(); 

     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = this; 
      listItems.Add(new someobjects("foo")); 
      listItems.Add(new someobjects("bar")); 
      listItems.Add(new someobjects("blah")); 
     } 

     private void ckbxSelectAll_Checked(object sender, RoutedEventArgs e) 
     { 
      foreach (someobjects item in listItems) 
      { 
       item.is_Selected = (bool)((CheckBox)sender).IsChecked; 
      } 
     } 

     public class someobjects : INotifyPropertyChanged 
     { 
      private string _text; 

      public string text 
      { 
       get { return _text; } 
       set { _text = value; OnPropertyChanged(); } 
      } 

      private bool _is_Selected; 

      public bool is_Selected 
      { 
       get { return _is_Selected; } 
       set { _is_Selected = value; OnPropertyChanged(); } 
      } 

      public someobjects(string t) 
      { 
       text = t; 
       is_Selected = false; 
      } 

      public event PropertyChangedEventHandler PropertyChanged; 

      protected void OnPropertyChanged([CallerMemberName] string propertyName = "") 
      { 
       var handler = PropertyChanged; 
       if (handler != null) 
        handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 
1

для тех, кто интересно о 2 решении я уже говорил, это событие должно быть присоединено к проверенным и непроверенным событиям SelectAll флажка

private void ckbxSelectAll_Checked(object sender, RoutedEventArgs e) 
    { 
     DockPanel dp = FindVisualChild<DockPanel>(pdflistView, 0); 
     ScrollContentPresenter scp = FindVisualChild<ScrollContentPresenter>(dp, 1); 
     VirtualizingStackPanel vsp = FindVisualChild<VirtualizingStackPanel>(scp, 0); 

     foreach (ListViewItem item in vsp.Children) 
     { 
      item.IsSelected = (bool)((CheckBox)sender).IsChecked; 
     } 
    } 

    private static T FindVisualChild<T>(UIElement element, int childindex) where T : UIElement 
    { 
     UIElement child = element; 
     while (child != null) 
     { 
      T correctlyTyped = child as T; 
      if (correctlyTyped != null) 
      { 
       return correctlyTyped; 
      } 

      child = VisualTreeHelper.GetChild(child, childindex) as UIElement; 
     } 
     return null; 
    } 
Смежные вопросы