为DataGridTemplatecolumn中的所有选中的复选框获取WPF Datagrid Row

时间:2013-07-02 02:43:51

标签: wpf checkbox wpfdatagrid celltemplate

我有一个DataGrid,显示Employees的一些名单信息。我添加了一个带有CheckBox的模板列。我想从所选(KeyIDs个选定的)行的所有行中获取CheckBox(从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>

3 个答案:

答案 0 :(得分:2)

Event

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

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

XAML中使用SelectedItem的{​​{1}}属性:

DataGrid

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的{​​{1}}。

此处KeyIDs是我假设所有与列相关的属性的VM,即DBDeleteViewModel等。

答案 1 :(得分:0)

您可以使用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;
    }

如果您只是调用此函数,它将仅返回第一个控件,但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; 
        }
    }
}

正如您所看到的,这种做法不是很有用,所以它不是很正确。您可以将MyChecked的属性OnPropertyChanged()添加到他的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

答案 2 :(得分:0)

在与每行绑定的类中定义bool属性(如IsRowSelected),将其绑定到Ischecked的{​​{1}}属性,然后删除{CheckBox的所有行{1}}中的{1}}。