【问题标题】:Fetch WPF Datagrid Row for all the selected checkboxs in DataGridTemplate column获取 DataGrid 模板列中所有选定复选框的 WPF 数据网格行
【发布时间】:2013-07-02 02:43:50
【问题描述】:

我有一个DataGrid,它显示了Employees 的一些花名册信息。我添加了一个带有CheckBox 的模板列。我想从选定(CheckBox selected)行的所有行中获取KeyIDs(从 DB 绑定)。这些KeyIDs 我必须传递给 SQL 以删除选定的行 (BtnDeleteSelected_Click)。请帮忙。

这是我的DataGrid

<DataGrid AutoGenerateColumns="False" Grid.Row="1" Height="555" HorizontalAlignment="Left" Margin="0,5,0,0" Name="dgRosterList" VerticalAlignment="Top" Width="980"   ItemsSource="{Binding}" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True" CanUserSortColumns="True"  AlternatingRowBackground="Gainsboro"  AlternationCount="2" IsEnabled="True" Grid.ColumnSpan="2">                
    <DataGrid.Columns>
        <DataGridTemplateColumn Width="30">
            <DataGridTemplateColumn.HeaderTemplate>
                <DataTemplate>
                    <CheckBox x:Name="all" Content="" Click="CheckBox_Click"/>
                </DataTemplate>
            </DataGridTemplateColumn.HeaderTemplate>

            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox Checked="chkSelect_Checked" Name="chkSelect"></CheckBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Sl No" Binding="{Binding SlNo}"/>
        <DataGridTextColumn Header="Key ID" Binding="{Binding KeyID}" Width="80" Visibility="Hidden"/>
        <DataGridTextColumn Header="Emp ID" Binding="{Binding Emp_ID}" Width="80"/>
        <DataGridTextColumn Header="Emp Name" Binding="{Binding Emp_Name}" Width="200"/>
        <DataGridTextColumn Header="Date" Binding="{Binding PDate, StringFormat={}{0:dd/MM/yyyy}}" Width="100"/>
        <DataGridTextColumn Header="Shift" Binding="{Binding Shift_Code}" Width="80"/>
        <DataGridTextColumn Header="In Time" Binding="{Binding InTime, StringFormat={}{0:hh:mm}}" Width="80"/>
        <DataGridTextColumn Header="Out Time" Binding="{Binding OutTime, StringFormat={}{0:hh:mm}}" Width="80"/>
        <DataGridTemplateColumn Header="Half Day" Width="80">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Name="IsHalfDay" Width="15" Height="15" Source="" />
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding HalfDay}" Value="Yes">
                                <Setter TargetName="IsHalfDay" Property="Source" Value="../Images/ico_tick.gif"/>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Off Day" Width="80">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Name="IsOffDay" Width="15" Height="15" Source="" />
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding OffDay}" Value="Yes">
                            <Setter TargetName="IsOffDay" Property="Source" Value="../Images/ico_tick.gif"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Delete" Width="75">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Name="btnDelete" Click="btnDelete_Click" Width="50" Height="20" ToolTip="Delete Roster" CommandParameter="{Binding Path=KeyID}" >
                        <Image Source="../Images/delete.png" Width="15" Height="19"/>
                    </Button>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Processed" Binding="{Binding Processed}"  Visibility="Hidden"/>
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <!--<Image Source="{Binding XPath=media:thumbnail/@url}"
                    Width="60" Height="60"/>-->
                <TextBlock Text="{Binding Path=WeeklyOffs}"/>
            </StackPanel>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

【问题讨论】:

    标签: wpf checkbox wpfdatagrid celltemplate


    【解决方案1】:

    Event

    private void chkSelect_Checked(object sender, RoutedEventArgs e)
    {
        dgRosterList.IsSynchronizedWithCurrentItem = true;
    }
    

    这将导致highlighting当前的row 就像它被选中一样。

    XAML 中使用DataGridSelectedItem 属性:

    SelectedItem="{Binding SelectedEmployeeData}"
    

    ViewModel中,定义SelectedEmployeeData的属性:

    private DeleteViewModel m_SelectedEmployeeData;
    
    public DeleteViewModel SelectedEmployeeData
    {
        get 
        { 
            return m_SelectedEmployeeData; 
        }
    
        set 
        { 
            m_SelectedEmployeeData = value;
    
            if (null != m_SelectedEmployeeData)
            {
                listToSend.Add(m_SelectedEmployeeData.KeyID);
            }
            else
            {
                listToSend.Remove(m_SelectedEmployeeData.KeyID);
            }
    
            OnPropertyChanged("SelectedEmployeeData");
        }
    }
    

    和:

    List<int> listToSend = new List<int>();
    

    lstSend 将包含要发送到DBKeyIDs

    这里DeleteViewModel 是VM,我假设与列相关的所有属性,即KeyIDEmp_ID 等都将被定义。

    【讨论】:

      【解决方案2】:

      您可以使用FindChild() 访问CheckBox

          public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
          {
              if (parent == null)
              {
                  return null;
              }
      
              T foundChild = null;
      
              int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
      
              for (int i = 0; i < childrenCount; i++)
              {
                  var child = VisualTreeHelper.GetChild(parent, i);
                  T childType = child as T;
      
                  if (childType == null)
                  {
                      foundChild = FindChild<T>(child, childName);
      
                      if (foundChild != null) break;
                  }
                  else
                      if (!string.IsNullOrEmpty(childName))
                      {
                          var frameworkElement = child as FrameworkElement;
      
                          if (frameworkElement != null && frameworkElement.Name == childName)
                          {
                              foundChild = (T)child;
      
                              break;
                          }
                          else
                          {
                              foundChild = FindChild<T>(child, childName);
      
                              if (foundChild != null)
                              {
                                  break;
                              }
                          }
                      }
                      else
                      {
                          foundChild = (T)child;
                          break;
                      }
              }
      
              return foundChild;
          }
      

      如果你只是调用这个函数,它将只返回 first 控件,但我们需要一个 CheckBox 来代替 Selected Row。要访问选定行的控件以将事件SelectionChanged 添加到要在其中起作用的DataGrid,这将给出Selected Row

      <DataGrid Name="MyDataGrid" SelectionChanged="MyDataGrid_SelectionChanged">
      
      private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
      {
          try
          {
              // Get the list of rows
              var row_list = GetDataGridRows(MyDataGrid);
      
              // Check the all rows
              foreach (DataGridRow single_row in row_list)
              {               
                  if (single_row.IsSelected == true)
                  {
                     CheckBox MyCheckBox = FindChild<CheckBox>(single_row, "MyCheckBox"); // here your CheckBox name
      
                      MessageBox.Show(MyCheckBox.IsChecked.ToString());
                  }
              }
          }
      
          catch 
          {
              throw new Exception("Can't get access to DataGridRow");
          }
      }
      

      GetDataGridRows() 的列表:

      public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
      {
          var itemsSource = grid.ItemsSource as IEnumerable;
      
          if (null == itemsSource)
          {
              yield return null; 
          }
      
          foreach (var item in itemsSource)
          {
              var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
      
              if (null != row)
              {
                  yield return row; 
              }
          }
      }
      

      如您所见,这种做法并不是很有用,因此也不是很正确。您可以将属性MyCheckedOnPropertyChanged() 添加到他的DataContext。示例:

          public class YourClass : INotifyPropertyChanged
          {
              private bool? myChecked = null;
      
              #region INotifyPropertyChanged values
      
              public event PropertyChangedEventHandler PropertyChanged;
      
              protected void OnPropertyChanged(string propertyName)
              {
                  if (this.PropertyChanged != null)
                  {
                      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                  }
              }
      
              #endregion
      
              public bool? MyChecked
              {
                  get
                  {
                      return myChecked;
                  }
      
                  set
                  {
                      myChecked = value;
                      OnPropertyChanged("myChecked");
                  }
              }
          }
      

      并像这样使用:

      <CheckBox x:Name="MyCheckBox" IsChecked="{Binding MyChecked}" />        
      

      每次更改属性时,都会触发OnPropertyChanged(),您可以进行一些操作。也就是说,尽量不要让他们的行为站在XAML的一边,而是站在你的数据一边,因为在第一种情况下,很难与DataGrid合作。

      【讨论】:

        【解决方案3】:

        在绑定到每一行的类中定义一个bool属性(如IsRowSelected),将其绑定到CheckBoxIschecked属性,然后您可以删除@987654325中IsRowSelected=True的所有行@。

        【讨论】:

          猜你喜欢
          • 2014-07-14
          • 2013-09-28
          • 2018-08-03
          • 2010-09-24
          • 2020-07-16
          • 2018-06-24
          • 1970-01-01
          • 1970-01-01
          • 2019-11-16
          相关资源
          最近更新 更多