WPF - 从datagridcell获取我的datatemplate时出现问题,它返回Nothing

时间:2015-09-10 23:47:59

标签: wpf vb.net

WPF对我来说还是新手,只用了几个星期。我从DataTemplate小区获取DataGrid时遇到了一些问题。我试过的每一种方式都给了我一个空洞的对象。找到了一些这方面的一般例子后,我无法在我的案例中找到它。他们中没有一个人像我一样试图这样做,我必须放弃功能,使其像我所见的例子一样。

我有DataGrid绑定到sql DataSetDataGrid只有一个DataGridTemplateColumn。它由基于DataTemplateSelector的自定义类提供。 DataGridTemplateColumn有几个控件绑定到DataSet中的字段,并且它有一个未绑定的控件。那个未绑定的控件是问题的根源。我需要得到用户放入一个未绑定控件的内容。他们只能这样做才能获得该单元格DataTemplate

sInsertSurveyResponse()中,当我尝试取出DataTemplate时,我得到一个空白对象,即VB术语中的Nothing。我尝试在单元级别和行级别获取模板但没有成功。

有人能说清楚为什么这不起作用吗?此外,当我在编写MS代码时使用VB工作时,我知道足够的C#来理解使用该语言的响应,所以不要忍住。谢谢。

下面包含完整的代码。

XAML

<Window x:Class="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:WpfApplication1"
        mc:Ignorable="d"
        Title="Survey" Height="450" Width="550" Loaded="Window_Loaded">
    <Grid x:Name="gridSurvey" Background="#66FFFFFF"  >
        <GroupBox x:Name="gbSurvey" Header="Please answer a few questions" Background="#FF3C9910" BorderBrush="Black" Width="500" Height="400" VerticalAlignment="Center" HorizontalAlignment="Center" >
            <GroupBox.HeaderTemplate>
                <DataTemplate>
                    <Grid>
                        <Border Name="Border" Margin="-2,0,-4,0" Padding="10,2" CornerRadius="5" BorderThickness="2" BorderBrush="#FF000000" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}" >
                            <ContentPresenter x:Name="GridHeaderContent" Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" />
                        </Border>
                        <Rectangle Height="12" Width="5" Margin="-2,0,0,0" StrokeThickness="0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Fill="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}"/>
                        <Rectangle Height="5" Margin="0,0,0,-2" StrokeThickness="0" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Fill="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}"/>
                        <Rectangle Height="12" Width="5" Margin="0,0,-4,0" StrokeThickness="0" VerticalAlignment="Bottom" HorizontalAlignment="Right" Fill="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}"/>
                    </Grid>
                </DataTemplate>
            </GroupBox.HeaderTemplate>
            <GroupBox.Effect>
                <DropShadowEffect Opacity="0.5"/>
            </GroupBox.Effect>
            <Grid>
                <DataGrid x:Name="dataGridSurveyQuestions" ItemsSource="{Binding Path=SurveyQuestionsDataBinding}" Margin="8,2,8,47" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalScrollBarVisibility="Hidden" HeadersVisibility="None" IsReadOnly="True" AutoGenerateColumns="False" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}" BorderThickness="0" GridLinesVisibility="None" >
                    <DataGrid.Resources>
                        <DataTemplate x:Key="dataTemplateQuestionType1" >
                            <Grid Width="475" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}">
                                <Label x:Name="QID" Content="{Binding QID}" Visibility="Collapsed" />
                                <Label x:Name="TID" Content="{Binding TID}" Visibility="Collapsed" />
                                <TextBlock x:Name="tbQuestion" Text="{Binding Question}" Margin="10,10,0,0" Width="325" Padding="0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" FontWeight="Normal" TextWrapping="Wrap" />
                                <ComboBox x:Name="surveyResponse" ToolTip="{Binding Instructions}" Width="125" Height="29" Margin="0,5,20,5" HorizontalAlignment="Right" VerticalAlignment="Top"  >
                                    <ComboBoxItem Tag="1" Content="1 (Best)"/>
                                    <ComboBoxItem Tag="2" Content="2"/>
                                    <ComboBoxItem Tag="3" Content="3 (Average)"/>
                                    <ComboBoxItem Tag="4" Content="4"/>
                                    <ComboBoxItem Tag="5" Content="5 (Worst)"/>
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                        <DataTemplate x:Key="dataTemplateQuestionType2" >
                            <Grid Width="475" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}">
                                <Label x:Name="QID" Content="{Binding QID}" Visibility="Collapsed" />
                                <Label x:Name="TID" Content="{Binding TID}" Visibility="Collapsed" />
                                <TextBlock x:Name="tbQuestion" Text="{Binding Question}" Margin="10,10,0,0" Width="325" Padding="0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" FontWeight="Normal" TextWrapping="Wrap" />
                                <ComboBox x:Name="surveyResponse" ToolTip="{Binding Instructions}" Width="125" Height="29" Margin="0,5,20,5" HorizontalAlignment="Right" VerticalAlignment="Top" >
                                    <ComboBoxItem Tag="1" Content="1 (Worst)"/>
                                    <ComboBoxItem Tag="2" Content="2"/>
                                    <ComboBoxItem Tag="3" Content="3 (Average)"/>
                                    <ComboBoxItem Tag="4" Content="4"/>
                                    <ComboBoxItem Tag="5" Content="5 (Best)"/>
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                        <DataTemplate x:Key="dataTemplateQuestionType3" >
                            <Grid Width="475" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}">
                                <Label x:Name="QID" Content="{Binding QID}" Visibility="Collapsed" />
                                <Label x:Name="TID" Content="{Binding TID}" Visibility="Collapsed" />
                                <TextBlock x:Name="tbQuestion" Text="{Binding Question}" Margin="10,10,0,0" Width="325" Padding="0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" FontWeight="Normal" TextWrapping="Wrap" />
                                <ComboBox x:Name="surveyResponse" ToolTip="{Binding Instructions}" Width="125" Height="29" Margin="0,5,20,5" HorizontalAlignment="Right" VerticalAlignment="Top" >
                                    <ComboBoxItem Tag="1" Content="1 (Best)"/>
                                    <ComboBoxItem Tag="2" Content="2"/>
                                    <ComboBoxItem Tag="3" Content="3"/>
                                    <ComboBoxItem Tag="4" Content="4"/>
                                    <ComboBoxItem Tag="5" Content="5 (Average)"/>
                                    <ComboBoxItem Tag="6" Content="6"/>
                                    <ComboBoxItem Tag="7" Content="7"/>
                                    <ComboBoxItem Tag="8" Content="8"/>
                                    <ComboBoxItem Tag="9" Content="9"/>
                                    <ComboBoxItem Tag="10" Content="10 (Worst)"/>
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                        <DataTemplate x:Key="dataTemplateQuestionType4" >
                            <Grid Width="475" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}">
                                <Label x:Name="QID" Content="{Binding QID}" Visibility="Collapsed" />
                                <Label x:Name="TID" Content="{Binding TID}" Visibility="Collapsed" />
                                <TextBlock x:Name="tbQuestion" Text="{Binding Question}" Margin="10,10,0,0" Width="325" Padding="0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" FontWeight="Normal" TextWrapping="Wrap" />
                                <ComboBox x:Name="surveyResponse" ToolTip="{Binding Instructions}" Width="125" Height="29" Margin="0,5,20,5" HorizontalAlignment="Right" VerticalAlignment="Top" >
                                    <ComboBoxItem Tag="1" Content="1 (Worst)"/>
                                    <ComboBoxItem Tag="2" Content="2"/>
                                    <ComboBoxItem Tag="3" Content="3"/>
                                    <ComboBoxItem Tag="4" Content="4"/>
                                    <ComboBoxItem Tag="5" Content="5 (Average)"/>
                                    <ComboBoxItem Tag="6" Content="6"/>
                                    <ComboBoxItem Tag="7" Content="7"/>
                                    <ComboBoxItem Tag="8" Content="8"/>
                                    <ComboBoxItem Tag="9" Content="9"/>
                                    <ComboBoxItem Tag="10" Content="10 (Best)"/>
                                </ComboBox>
                            </Grid>
                        </DataTemplate>
                        <DataTemplate x:Key="dataTemplateQuestionType5" >
                            <Grid Width="475" Background="{Binding Background, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}">
                                <Label x:Name="QID" Content="{Binding QID}" Visibility="Collapsed" />
                                <Label x:Name="TID" Content="{Binding TID}" Visibility="Collapsed" />
                                <TextBlock x:Name="tbQuestion" Text="{Binding Question}" Margin="10,10,0,0" Width="325" Padding="0" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" FontWeight="Normal" TextWrapping="Wrap" />
                                <TextBox x:Name="surveyResponse" ToolTip="{Binding Instructions}" Width="125" Height="29" Margin="0,5,20,5" HorizontalAlignment="Right" VerticalAlignment="Top" />
                            </Grid>
                        </DataTemplate>
                    </DataGrid.Resources>
                    <DataGrid.CellStyle>
                        <Style TargetType="{x:Type DataGridCell}">
                            <Setter Property="BorderThickness" Value="0"/>
                        </Style>
                    </DataGrid.CellStyle>
                    <DataGrid.Columns>
                        <DataGridTemplateColumn>
                            <DataGridTemplateColumn.CellTemplateSelector>
                                <local:SurveyResponseTemplateSelector 
                                                    Type1Template="{StaticResource dataTemplateQuestionType1}"
                                                    Type2Template="{StaticResource dataTemplateQuestionType2}"
                                                    Type3Template="{StaticResource dataTemplateQuestionType3}"
                                                    Type4Template="{StaticResource dataTemplateQuestionType4}"
                                                    Type5Template="{StaticResource dataTemplateQuestionType5}"/>
                            </DataGridTemplateColumn.CellTemplateSelector>
                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </DataGrid>
                <Button x:Name="btnCancelSurvey" Content="Cancel" Width="85" HorizontalAlignment="Left" Margin="80,0,0,10" VerticalAlignment="Bottom"  />
                <Button x:Name="btnSaveSurvey" Content="Done" Width="85" HorizontalAlignment="Right" Margin="0,0,80,10" VerticalAlignment="Bottom"  />
            </Grid>
        </GroupBox>
    </Grid>

</Window>

VB

Imports MySql.Data.MySqlClient
Imports System.Data
Imports System.Windows.Controls.Primitives

Public Class SurveyResponseTemplateSelector
    Inherits DataTemplateSelector
    Public Property Type1Template() As DataTemplate
        Get
            Return m_Type1Template
        End Get
        Set
            m_Type1Template = Value
        End Set
    End Property
    Private m_Type1Template As DataTemplate

    Public Property Type2Template() As DataTemplate
        Get
            Return m_Type2Template
        End Get
        Set
            m_Type2Template = Value
        End Set
    End Property
    Private m_Type2Template As DataTemplate

    Public Property Type3Template() As DataTemplate
        Get
            Return m_Type3Template
        End Get
        Set
            m_Type3Template = Value
        End Set
    End Property
    Private m_Type3Template As DataTemplate

    Public Property Type4Template() As DataTemplate
        Get
            Return m_Type4Template
        End Get
        Set
            m_Type4Template = Value
        End Set
    End Property
    Private m_Type4Template As DataTemplate

    Public Property Type5Template() As DataTemplate
        Get
            Return m_Type5Template
        End Get
        Set
            m_Type5Template = Value
        End Set
    End Property
    Private m_Type5Template As DataTemplate

    Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
        Dim drvItem As DataRowView = TryCast(item, DataRowView)

        If drvItem IsNot Nothing Then

            Dim TID As Integer = drvItem.Row.ItemArray(1)

            Select Case TID
                Case 1
                    Return Type1Template
                    Exit Select
                Case 2
                    Return Type2Template
                    Exit Select
                Case 3
                    Return Type3Template
                    Exit Select
                Case 4
                    Return Type4Template
                    Exit Select
                Case 5
                    Return Type5Template
                    Exit Select
                Case Else
                    Return MyBase.SelectTemplate(item, container)
            End Select

        Else
            Return MyBase.SelectTemplate(item, container)
        End If

    End Function

End Class

Class MainWindow
    Dim gConn As MySqlConnection = New MySqlConnection("server=localhost;user id=xxxxx;password=xxxxxx;database=xxxxx")

    Private Function fFindVisualChild(Of childItem As DependencyObject)(ByVal obj As DependencyObject) As childItem

        Dim i As Integer

        For i = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1

            Dim child As DependencyObject = VisualTreeHelper.GetChild(obj, i)
            If ((Not child Is Nothing) And (TypeOf child Is childItem)) Then
                Return child
            End If

            Dim childOfChild As childItem = Me.fFindVisualChild(Of childItem)(child)
            If (Not childOfChild Is Nothing) Then
                Return childOfChild
            End If

        Next i

        Return Nothing

    End Function

    Private Sub sInsertSurveyResponse()
        ' Note to self: This is full of testing code, clean it up later.
        Try
            gConn.Open()

            Using sqlTran As MySqlTransaction = gConn.BeginTransaction()
                Try
                    Dim allOK As Boolean = True
                    Dim affectedRowKnt As Integer = 0
                    Dim errorMessage As String = ""
                    Dim insertResponseSQL As String = "INSERT INTO meals.tbl_survey_responses(int_Question_ID,char_Response) " +
                                                      "VALUES (@int_Question_ID,@char_Response);"

                    Using cmd As New MySqlCommand(insertResponseSQL, gConn, sqlTran)
                        For x As Integer = 0 To dataGridSurveyQuestions.Items.Count - 1
                            Dim row As DataGridRow = DirectCast(dataGridSurveyQuestions.ItemContainerGenerator.ContainerFromItem(dataGridSurveyQuestions.Items.Item(x)), DataGridRow)
                            Dim questionID As String = ""
                            Dim surveyResponse As String = ""

                            If row IsNot Nothing Then
                                Dim presenter As DataGridCellsPresenter = fFindVisualChild(Of DataGridCellsPresenter)(row)
                                Dim template As DataTemplate = presenter.ItemTemplate

                                ' Testing code, try to get the controls from the cell's item template, this FAILS
                                If template IsNot Nothing Then
                                    Dim QID As Label = DirectCast(template.FindName("QID", presenter), Label)
                                    Dim TID As Label = DirectCast(template.FindName("TID", presenter), Label)

                                    questionID = QID.Content
                                    If Not TID.Content.Equals("5") Then
                                        surveyResponse = DirectCast(DirectCast(template.FindName("surveyResponse", presenter), ComboBox).SelectedItem, ComboBoxItem).Tag
                                    Else
                                        surveyResponse = DirectCast(template.FindName("surveyResponse", presenter), TextBox).Text
                                    End If

                                Else
                                    Dim presenter2 As DataGridDetailsPresenter = fFindVisualChild(Of DataGridDetailsPresenter)(row)
                                    Dim template2 As DataTemplate = presenter2.ContentTemplate

                                    ' Testing code, try to get the controls from the row's content template, this also FAILS
                                    If template IsNot Nothing Then
                                        Dim QID As Label = DirectCast(template.FindName("QID", presenter), Label)
                                        Dim TID As Label = DirectCast(template.FindName("TID", presenter), Label)

                                        questionID = QID.Content
                                        If Not TID.Content.Equals("5") Then
                                            surveyResponse = DirectCast(DirectCast(template.FindName("surveyResponse", presenter), ComboBox).SelectedItem, ComboBoxItem).Tag
                                        Else
                                            surveyResponse = DirectCast(template.FindName("surveyResponse", presenter), TextBox).Text
                                        End If

                                    Else
                                        allOK = False
                                        MessageBox.Show("Got NOTHING in either template...")
                                    End If
                                End If
                            Else
                                allOK = False
                                MessageBox.Show("Got NOTHING in ROW...")
                            End If

                            If allOK Then
                                cmd.Parameters.AddWithValue("@int_Question_ID", questionID)
                                cmd.Parameters.AddWithValue("@char_Response", surveyResponse)
                                affectedRowKnt = cmd.ExecuteNonQuery()
                                cmd.Parameters.Clear()

                                If affectedRowKnt = 0 Then Exit For
                            End If

                        Next x
                    End Using

                    If affectedRowKnt = 0 Then
                        allOK = False
                        errorMessage = "Unable to add all response records."
                    End If

                    If allOK Then
                        sqlTran.Commit()
                    Else
                        MessageBox.Show(errorMessage, "Save Survey Response Failed", MessageBoxButton.OK, MessageBoxImage.Error)
                        sqlTran.Rollback()
                    End If

                Catch ex As Exception
                    MessageBox.Show(ex.ToString, "Error Message", MessageBoxButton.OK, MessageBoxImage.Error)
                    sqlTran.Rollback()
                End Try
            End Using

        Catch ex As Exception
            MessageBox.Show(ex.ToString, "Error Message", MessageBoxButton.OK, MessageBoxImage.Error)
        Finally
            gConn.Close()
        End Try
    End Sub

    Private Sub sRefreshSurveyQuestions()
        Try
            gConn.Open()

            Dim sql As String = "SELECT q.int_Question_ID QID, q.int_Question_Type_ID TID, q.char_Question Question, t.char_Title Instructions 
                                 FROM   meals.tbl_survey_questions q,
                                        meals.tbl_survey_question_types t
                                 WHERE  q.bool_Active = 1
                                   AND  q.int_Question_Type_ID = t.int_Question_Type_ID
                                 ORDER  BY q.char_SortOrder, q.char_Question;"
            Dim cmd As MySqlCommand = New MySqlCommand(sql, gConn)
            Dim adp As MySqlDataAdapter = New MySqlDataAdapter(cmd)
            Dim ds As DataSet = New DataSet()

            adp.Fill(ds, "SurveyQuestionsDataBinding")
            dataGridSurveyQuestions.DataContext = ds

        Catch ex As Exception
            MessageBox.Show(ex.ToString, "Error Message", MessageBoxButton.OK, MessageBoxImage.Error)
        Finally
            gConn.Close()
        End Try
    End Sub

    Private Sub btnSaveSurvey_Click(sender As Object, e As RoutedEventArgs) Handles btnSaveSurvey.Click
        sInsertSurveyResponse()
    End Sub

    Private Sub btnCancelSurvey_Click(sender As Object, e As RoutedEventArgs) Handles btnCancelSurvey.Click
        sRefreshSurveyQuestions()
    End Sub

    Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
        sRefreshSurveyQuestions()
    End Sub
End Class

SQL

CREATE TABLE tbl_survey_questions (
    int_Question_ID INT(10) NOT NULL AUTO_INCREMENT,
    int_Question_Type_ID INT(10) NOT NULL,
    char_Question VARCHAR(1000) NOT NULL,
    char_SortOrder VARCHAR(5) DEFAULT 'MMMMM',
    bool_Active BOOLEAN NOT NULL,
    PRIMARY KEY (int_Question_ID)
);

CREATE TABLE tbl_survey_question_types (
    int_Question_Type_ID INT(10) NOT NULL AUTO_INCREMENT,
    char_Title VARCHAR(100) NOT NULL,
    PRIMARY KEY (int_Question_Type_ID)
);

CREATE TABLE tbl_survey_responses (
    int_Response_ID INT(10) NOT NULL AUTO_INCREMENT,
    dt_Response_Datetime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    int_Question_ID INT(10) NOT NULL,
    char_Response VARCHAR(100) NOT NULL,
    PRIMARY KEY (int_Response_ID)
);

insert into tbl_survey_question_types (int_Question_Type_ID, char_Title)
VALUES (1, 'Ranked 1 to 5, with 1 as the most favorable response.');
insert into tbl_survey_question_types (int_Question_Type_ID, char_Title)
VALUES (2, 'Ranked 1 to 5, with 1 as the least favorable response.');
insert into tbl_survey_question_types (int_Question_Type_ID, char_Title)
VALUES (3, 'Ranked 1 to 10, with 1 as the most favorable response.');
insert into tbl_survey_question_types (int_Question_Type_ID, char_Title)
VALUES (4, 'Ranked 1 to 10, with 1 as the least favorable response.');
insert into tbl_survey_question_types (int_Question_Type_ID, char_Title)
VALUES (5, 'Free form, fill in with your text.');

insert into tbl_survey_questions (int_Question_Type_ID, char_Question, char_SortOrder, bool_Active) 
values (4, 'At the moment how would you rate thing 1?', 'MMAMM', true);
insert into tbl_survey_questions (int_Question_Type_ID, char_Question, char_SortOrder, bool_Active) 
values (1, 'At the moment how would you rate thing 2?', 'MMDMM', true);
insert into tbl_survey_questions (int_Question_Type_ID, char_Question, char_SortOrder, bool_Active) 
values (3, 'At the moment how would you rate thing 3?', 'MMEMM', true);
insert into tbl_survey_questions (int_Question_Type_ID, char_Question, char_SortOrder, bool_Active) 
values (3, 'At the moment how would you rate thing 4?', 'MMCMM', true);
insert into tbl_survey_questions (int_Question_Type_ID, char_Question, char_SortOrder, bool_Active) 
values (2, 'At the moment how would you rate thing 5?', 'MMBMM', true);

1 个答案:

答案 0 :(得分:0)

据我所知,我的DataTemplate中找不到DataGrid。所以,我已经改变了齿轮,然后分开DataGridCell的视觉控制树,以便直接访问未绑定的控件。通过名称和类型获取子元素是必需的,因此我用fFindVisualChildByName()替换了我使用的fFindVisualChild()。

Private Function fFindVisualChildByName(Of childItem As DependencyObject)(parent As DependencyObject, childName As String) As childItem
    Dim foundChild As childItem = Nothing
    If parent IsNot Nothing Then
        For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(parent) - 1
            Dim child = VisualTreeHelper.GetChild(parent, i)
            Dim childType As childItem = TryCast(child, childItem)

            If childType Is Nothing Then
                foundChild = fFindVisualChildByName(Of childItem)(child, childName)

                If foundChild IsNot Nothing Then
                    Exit For
                End If
            ElseIf Not String.IsNullOrEmpty(childName) Then
                Dim frameworkElement = TryCast(child, FrameworkElement)
                If frameworkElement IsNot Nothing AndAlso frameworkElement.Name = childName Then
                    foundChild = DirectCast(child, childItem)
                    Exit For
                End If
            Else
                foundChild = DirectCast(child, childItem)
                Exit For
            End If
        Next
    End If

    Return foundChild
End Function

现在,这是一个递归函数,所以它可能是一个资源匮乏,应该谨慎使用。出于这个原因,我尽量避免从树顶使用它。在fFindVisualChildByName()到位后,我更改了sInsertSurveyResponse(),删除了测试代码并使用了新函数。

Private Sub sInsertSurveyResponse()
    Try
        gConn.Open()

        Using sqlTran As MySqlTransaction = gConn.BeginTransaction()
            Try
                Dim allOK As Boolean = True
                Dim rows As Integer = 0
                Dim newID As Int16 = 0
                Dim errorMessage As String = ""
                Dim getNextIDSQL As String = "SELECT IfNull(MAX(int_Response_ID),0)+1 FROM meals.tbl_survey_responses;"
                Dim insertResponseSQL As String = "INSERT INTO meals.tbl_survey_responses(int_Response_ID,int_Question_ID,char_Response) " +
                                                  "VALUES (@int_Response_ID,@int_Question_ID,@char_Response);"

                Using cmd As New MySqlCommand(getNextIDSQL, gConn, sqlTran)
                    newID = Convert.ToInt16(cmd.ExecuteScalar())
                End Using

                Using cmd As New MySqlCommand(insertResponseSQL, gConn, sqlTran)
                    For x As Integer = 0 To dataGridSurveyQuestions.Items.Count - 1
                        Dim dgRow As DataGridRow = DirectCast(dataGridSurveyQuestions.ItemContainerGenerator.ContainerFromItem(dataGridSurveyQuestions.Items.Item(x)), DataGridRow)
                        Dim dgCell As DataGridCell = fFindVisualChildByName(Of DataGridCell)(dgRow, Nothing)
                        Dim QID As Label = fFindVisualChildByName(Of Label)(dgCell, "QID")
                        Dim TID As Label = fFindVisualChildByName(Of Label)(dgCell, "TID")
                        Dim surveyResponse As String = ""

                        If Not TID.Content.Equals("5") Then
                            Dim cbResponse As ComboBox = fFindVisualChildByName(Of ComboBox)(dgCell, "surveyResponse")
                            If cbResponse.SelectedIndex >= 0 Then
                                surveyResponse = DirectCast(cbResponse.SelectedItem, ComboBoxItem).Tag
                            End If
                        Else
                            Dim tbResponse As TextBox = fFindVisualChildByName(Of TextBox)(dgCell, "surveyResponse")
                            surveyResponse = tbResponse.Text
                        End If

                        If surveyResponse.Length > 0 Then
                            cmd.Parameters.AddWithValue("@int_Response_ID", newID.ToString())
                            cmd.Parameters.AddWithValue("@int_Question_ID", QID.Content)
                            cmd.Parameters.AddWithValue("@char_Response", surveyResponse)
                            rows = cmd.ExecuteNonQuery()
                            If rows = 0 Then
                                allOK = False
                                errorMessage = "Unable to add all response records."
                                Exit For
                            Else
                                cmd.Parameters.Clear()
                            End If
                        Else
                            allOK = False
                            errorMessage = "Blank responses are not valid.  Save failed."
                            Exit For
                        End If
                    Next x
                End Using

                If allOK Then
                    sqlTran.Commit()
                Else
                    MessageBox.Show(errorMessage, "Save Survey Response Failed", MessageBoxButton.OK, MessageBoxImage.Error)
                    sqlTran.Rollback()
                End If

            Catch ex As Exception
                MessageBox.Show(ex.ToString, "Error Message", MessageBoxButton.OK, MessageBoxImage.Error)
                sqlTran.Rollback()
            End Try
        End Using

    Catch ex As Exception
        MessageBox.Show(ex.ToString, "Error Message", MessageBoxButton.OK, MessageBoxImage.Error)
    Finally
        gConn.Close()
    End Try
End Sub

最后,我从tbl_survey_responses和自动编号中删除了主键。从答案的角度来看,这并不重要,但是如果以此处的代码为例。我喜欢有效的例子,我不会像我一样喜欢看。

所以,这就是我为自己找到的答案。我仍然不知道为什么DataTemplate在我的情况下是空的,而不是为了其他人。我只能猜测它与我使用DataTemplateSelector有关。