2013-12-16 31 views
0

我有一个报告页面,显示我们报告的一组数据的视图。这个视图有大约40个字段。用户可以查询和过滤数据以获得他们所需的数据,然后将其导出到Excel报告中,然后自动通过电子邮件发送给需要查看信息的管理。复选框选择全部或全部取消选择不受数据集绑定的列表视图

因为并非所有的字段都是每个报告都需要的,我也有一个列表框旁边的复选框来隐藏或显示任何字段。我一直在试图找出如何通过选择标题中的复选框来选中或取消选中所有复选框。列表框的xaml绑定到网格中字段的IsVisible属性,看起来像这样。

<ListView ItemsSource="{Binding Columns, ElementName=reportGrid}" SelectionMode="Multiple"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Width="50"> 
       <GridViewColumn.HeaderTemplate> 
        <DataTemplate> 
          <CheckBox x:Name="checkall" IsChecked="{Binding IsMainSelected}" Tag="{Binding Source={StaticResource Spy}, Path=DataContext}" /> 
        </DataTemplate> 
       </GridViewColumn.HeaderTemplate>              <GridViewColumn.CellTemplate>            
        <DataTemplate > 
         <CheckBox IsChecked="{Binding IsVisible}" /> 
        </DataTemplate> 
      </GridViewColumn.CellTemplate> 
      </GridViewColumn> 
           <GridViewColumn Header="Field" DisplayMemberBinding="{Binding Header}" Width="100"></GridViewColumn> 
      </GridView> 
    </ListView.View> 

的间谍静态资源的引用来自这篇文章。 http://www.codeproject.com/Articles/27432/Artificial-Inheritance-Contexts-in-WPF

但是,我遇到的每个解决方案的问题是这样的事实,即listview中的复选框绑定到数据集。在这种情况下,复选框被绑定到网格中的列的可见性(在页面上的对象上)。我尝试过的所有东西都失败了。这可能是一个简单的解决方案,但如果我能弄明白的话,我很难。任何帮助,将不胜感激。

更新: 我想出了一个解决方案,使用后面的代码来解决这个问题。如果有一种方法可以在不使用代码的情况下做到这一点,那么我就是所有人都知道的,但这是相当简单直接的第一步和第二步,它并没有真正打破逻辑脱离代码的规则。

的XAML

<ListView x:Name="lv" ItemsSource="{Binding Columns, ElementName=reportGrid}" Grid.Column="0" Grid.Row="1" 
           Margin="5,160,25,30" SelectionMode="Multiple">       
         <ListView.View> 
          <GridView x:Name="gl"> 
           <GridViewColumn Width="50"> 
            <GridViewColumn.CellTemplate > 
             <DataTemplate x:Name="fieldChecked" > 
              <CheckBox IsChecked="{Binding IsVisible}" /> 
             </DataTemplate> 
            </GridViewColumn.CellTemplate> 
            <CheckBox Margin="0" x:Name="chkSelectAll" Click="chkSelectAll_Click" IsChecked="True" /> 
           </GridViewColumn> 
           <GridViewColumn Header="Check/Uncheck All" DisplayMemberBinding="{Binding Header}" Width="110"></GridViewColumn> 
          </GridView> 
         </ListView.View> 
        </ListView> 

背后

private void chkSelectAll_Click(object sender, RoutedEventArgs e) 
    { 
     if (chkSelectAll.IsChecked.Value == true) 
     { 
      for (int i = 0; i < lv.Items.Count; i++) 
      {      
       ListViewItem lvi = (ListViewItem)lv.ItemContainerGenerator.ContainerFromItem(lv.Items[i]); 

       if (lvi != null) 
       { 
        CheckBox c = lvi.FindChildByType<CheckBox>(); 
        c.IsChecked = true;       
       } 
      } 
     } 
     else 
     {     
      for (int i = 0; i < lv.Items.Count; i++) 
      { 
       ListViewItem lvi = (ListViewItem)lv.ItemContainerGenerator.ContainerFromItem(lv.Items[i]); 
       if (lvi != null) 
       { 
        CheckBox c = lvi.FindChildByType<CheckBox>(); 
        c.IsChecked = false; 
       } 
      }     
     } 
    } 

一个需要注意的代码是列表视图我不得不向下滚动到下看到所有的字段。如果我没有这样做,它不会取消选中所有的字段。如果(lvi!= null),我也必须在代码行 中,因为如果你没有向下滚动,它会认为列表中的项目是空的并且崩溃。

无论如何,这不是完美的,但这是我如何解决它。使用MVVM的任何更好的解决方案都不是那么复杂而且难以实现,请赐教。

感谢

+0

更新...我无法弄清楚如何使用MVVM范例来解决方案,但是使用后面的代码做了一些事情。我发现有时后面的代码是最简单的方法。只要我们在代码背后没有任何真正的逻辑,那么谁在乎呢?无论如何。 xml – Paul

回答

0

哇..这是一个老问题,但不管是什么原因仍然没有得到答复。

诉诸于VisualTreeHelper类型的东西几乎从来都不是WPF中的最佳方法。它甚至比适当的基于DataBinding的方法“更容易”。在这种情况下,由于您正在处理UI特定的问题(显示或隐藏DataGrid的列),因此不存在ViewModel,因此MVVM不适用于此处,并且后面的代码完全有效。

但是,你看问题的错误的结束:试图操纵的复选框(绑定目标),而不是简单地操纵绑定来源(列本身):

private void chkSelectAll_Click(object sender, RoutedEventArgs e) 
{ 
    var visible = chkSelectAll.IsChecked ?? false; 
    foreach (var column in reportGrid.Columns) 
     column.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;  
} 

通过修改Visibility属性的值,每列的只读IsVisible属性将被更新,绑定将携带新值到每个相应CheckBox的CheckBox.IsChecked属性。

0

如果有人像我一样绊倒了这个恶作剧,有一个很好的方法来解决保罗提到的滚动问题:只需滚动代码隐藏!

listView.ScrollIntoView(listView.Items[listView.Items.Count - 1]); 
listView.ScrollIntoView(listView.Items[0]); 

之后,你可以做的ItemContainerGenerator东西没有得到空。

如果您想优化响应能力(特别是对于不经常更改的大型列表):当listView的源内容发生更改时,您只需查询ItemContainerGenerator。因此,如果您将复选框放在单独的列表中,则只需在用户第一次单击(全)选择复选框时查询ItemContainerGenerator ...

但是,您应该在De)选择所有复选框,因为如果在设置itemsSource并执行滚动之后立即为CheckBoxes查询ItemContainerGenerator,那么最终还是会出现空值(我认为,因为GUI没有足够的时间来正确呈现ListView那时候)。

相关问题