获取WPF中CheckBox单元格的布尔值

时间:2016-04-13 09:32:46

标签: wpf vb.net checkbox casting wpfdatagrid

我有DataGrid在行的每个第一个单元格中都有Checkbox。我想循环遍历DataGrid行并在检查该单元格中的Checkbox时获取行。

这是检查DataGrid

的代码

根据Ilan的回答编辑

Private Sub ApproveBtn_Clicked(sender As Object, e As RoutedEventArgs)


    For i As Integer = 0 To TimeSheetAppDGrid.Items.Count - 1

        TimeSheetAppDGrid.SelectedItem = TimeSheetAppDGrid.Items(i)
        Dim row As Row = DirectCast(TimeSheetAppDGrid.SelectedItems(0), Row)

        Dim mycheckbox = TryCast(TimeSheetAppDGrid.Columns(0).GetCellContent(TimeSheetAppDGrid.Items(i)), ContentPresenter)
        If mycheckbox Is Nothing Then
            Return
        End If
        Dim checkBox = GetAllVisualChildren(mycheckbox).OfType(Of CheckBox)().FirstOrDefault(Function(box) box.Name = "chkSelectAll")
        If checkBox Is Nothing Then
            Return
        End If

        Dim isChecked = checkBox.Checked

        If isChecked = True Then

            MsgBox(row.Mark)

        End If

    Next


End Sub

下面的代码似乎不被VB.NET接受,导致编译错误,表示" Value of type 'FrameworkElement' cannot be converted to 'CheckBox'."在搜索网页后,几乎所有答案都包含此代码,但在C#中,我将其转换为:

Dim mycheckbox As CheckBox = TryCast(TimeSheetAppDGrid.Columns(0).GetCellContent(TimeSheetAppDGrid.SelectedItems(0)), CheckBox)

link是我获取代码的地方。下面是C#的原始代码行:

CheckBox mycheckbox = myGrid.Columns[5].GetCellContent(myGrid.Items[i]) as CheckBox;

这是我对DataGrid的xaml:

<DataGrid Name ="TimeSheetAppDGrid" Margin="16,200,48,0"  CanUserSortColumns="False" CanUserReorderColumns="False" CanUserAddRows="False" AutoGenerateColumns="False"  SelectionUnit="FullRow"
                  materialDesign:DataGridAssist.CellPadding="13 8 8 8" materialDesign:DataGridAssist.ColumnHeaderPadding="8"  IsReadOnly="True" SelectionMode="Single"  >

    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridRow}"  BasedOn="{StaticResource MaterialDesignDataGridRow}">
            <EventSetter Event="MouseDoubleClick" Handler="Row_DoubleClick"/>
        </Style>
    </DataGrid.Resources>

    <DataGrid.Columns>

        <DataGridTemplateColumn>
            <DataGridTemplateColumn.Header>
                <CheckBox Name="AllChkBox" />
            </DataGridTemplateColumn.Header>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox Name="chkSelectAll" Margin="3.5 0 0 0"
              IsChecked="{Binding IsChecked, ElementName=AllChkBox,
                                  Mode=OneWay}"/>
                </DataTemplate> 
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTextColumn Binding="{Binding Path=Mark}" Header="Mark" Width="120" MaxWidth="120"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=ProjectCode}" Header="Project Code" Width="130" MaxWidth="130"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=Project}" Header="Project" Width="250" MaxWidth="250"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=PM}" Header="Project Manager" Width="230" MaxWidth="230"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=Activity}" Header="Activity" Width="600" MaxWidth="600"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=Today}" Header="Date" Width="200" MaxWidth="200"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=Regular}" Header="Regular" Width="130" MaxWidth="130"
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>
        <materialDesign:MaterialDataGridTextColumn Binding="{Binding Path=Overtime}" Header="Overtime" Width="130" MaxWidth="130"                                            
         EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}">
            <DataGridTextColumn.HeaderStyle>
                <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}">
                    <Setter Property="HorizontalAlignment" Value="Left" />
                </Style>
            </DataGridTextColumn.HeaderStyle>
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="HorizontalAlignment" Value="Left" />
                </Style>
            </DataGridTextColumn.ElementStyle>
        </materialDesign:MaterialDataGridTextColumn>
    </DataGrid.Columns>

    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource MaterialDesignDataGridCell}">
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

您必须查看使用Snoop生成的可视树,以便您的演员阵容正常运行。

最简单的方法是在Dictionary<int, DataGridRow>的{​​{1}}事件后不断更新Checked/Unchecked

对不起,代码在C#中。

XAML:

CheckBox

代码:

<CheckBox Name="AllChkBox" Checked="AllChkBox_Checked" Unchecked="AllChkBox_Unchecked" />

<CheckBox Name="chkSelectAll" Margin="3.5 0 0 0" 
          Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked" 
          IsChecked="{Binding IsChecked, ElementName=AllChkBox, Mode=OneWay}"/>

答案 1 :(得分:0)

在我看来,您采用的解决方案存在一些概念错误:

  

CheckBox mycheckbox = myGrid.Columns [5] .GetCellContent(myGrid.Items [i])为CheckBox;

我已经检查了它,当我们使用DataGridTemplateColumn.CellTemplate时,就像你的情况一样,接受的值(mycheckbox)是ContentPresenter,因为在单元格后面有DataTemplate(因为你正在使用DataTemplate) )。这就是代码实际上无法正常工作的原因。

我建议你的解决方案是从ContentPresenter获取复选框对象(代码在C#中你必须将其转换为VB),因为它是ContentPresenter的可视子代(你可以在Snoop)。

UpdateHere是GetAllVisualChildren代码:

public static class VisualTreeHelperExtensions
{
    public static T FindParent<T>(this DependencyObject child) where T : DependencyObject
    {
        while (true)
        {
            //get parent item
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);

            //we've reached the end of the tree
            if (parentObject == null) return null;

            //check if the parent matches the type we're looking for
            T parent = parentObject as T;
            if (parent != null)
                return parent;
            child = parentObject;
        }
    }

    public static List<DependencyObject> GetAllVisualChildren(this DependencyObject parent)
    {
        var resultedList = new List<DependencyObject>();
        var visualQueue = new Queue<DependencyObject>();
        visualQueue.Enqueue(parent);

        do
        {
            var depObj = visualQueue.Dequeue();
            var childrenCount = VisualTreeHelper.GetChildrenCount(depObj);

            for (int i = 0; i < childrenCount; i++)
            {
                var v = VisualTreeHelper.GetChild(depObj, i);
                visualQueue.Enqueue(v);
            }

            resultedList.Add(depObj);
        } while (visualQueue.Count > 0);

        resultedList.RemoveAt(0);
        return resultedList;
    }

}

下一步是为了将VisualTreeHelperExtensions类导入VB

  1. 创建一个C#类库作为解决方案的一部分。
  2. 将VisualTreeHelperExtensions类添加到新创建的项目中。
  3. 编译您的C#类库。
  4. 将新的create(和编译)类库添加到vb.net项目中作为参考(dll)。
  5. 更新#3 - 更改了vb代码

    Dim mycheckbox = TryCast(TimeSheetAppDGrid.Columns(0).GetCellContent(TimeSheetAppDGrid.Items(0)), ContentPresenter)
        If mycheckbox Is Nothing Then
            Return
        End If
        Dim checkBox = mycheckbox.GetAllVisualChildren().OfType(Of CheckBox)().FirstOrDefault(Function(box) box.Name = "chkSelectAll")
        If checkBox Is Nothing Then
            Return
        End If
    
        Dim isChecked = checkBox.IsChecked
    
        If isChecked = True Then
    
            MsgBox("Checked")
    
        End If
    

    VB.net CheckBox示例

    1. CheckBox Control WPF In VB.NET.

    2. CheckBox Class in .Net Framework(no any restriction to vb)

    3. 因为所有.net CheckBox都有其IsChecked布尔状态演示者。

      问候。

答案 2 :(得分:0)

修改

好的,这里有一个更精致的方法来实现你所需要的,而不必搜索可视树寻找复选框(再次在c#中,但希望不应该难以翻译)。 首先,我创建了一个绑定到其上的Student类来实现INotifyPropertyChanged:

    public class Student:INotifyPropertyChanged
    {
        private bool _isChecked;

        public bool IsChecked
        {
            get { return _isChecked; }
            set { _isChecked = value;
                OnPropertyChanged("IsChecked");
            }
        }
        public string Mark { get; set; }
        public string ProjectCode { get; set; }
        public string Project { get; set; }
        public string PM { get; set; }
        public string Activity { get; set; }
        public DateTime Today { get; set; }
        public string Regular { get; set; }
        public string Overtime { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

然后我在测试数据的数据网格中添加一行:

            TimeSheetAppDGrid.ItemsSource = new List<Student>()
            {
                new Student { ProjectCode="Project1",Mark = "A",Today = DateTime.Today}
            };

在数据模板的XAML中,我已将绑定更改为而不是绑定到标题复选框,但绑定到学生IsChecked属性,并且我添加了一个单击的处理程序对于标题单元格中的AllChkBox复选框:

  <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <CheckBox Click="AllChkBox_OnClick" Name="AllChkBox" />
                    </DataGridTemplateColumn.Header>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox  Name="chkSelectAll" Margin="3.5 0 0 0"
              IsChecked="{Binding Path=IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

对于AllChkBox单击的处理程序(AllChkBox_OnClick),我遍历每个数据源(即Student)并将IsChecked属性切换为AllChkBox选中的值:

        private void AllChkBox_OnClick(object sender, RoutedEventArgs e)
        {

            foreach (var s in TimeSheetAppDGrid.ItemsSource)
            {
                Student st = s as Student;

                st.IsChecked = (bool) AllChkBox.IsChecked;
            }

        }

现在可以查询每个项目源(即学生)的IsChecked属性(绑定到相应的复选框单元格),而无需绕过检查复选框(借口双关语),即

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    foreach (var source in TimeSheetAppDGrid.ItemsSource)
    {
        Student st = source as Student;

        if (st.IsChecked)
            MessageBox.Show("Is Checked");
    }
}