代码之家  ›  专栏  ›  技术社区  ›  knutter539

WPF Datagrid将第二个DB表显示为组合框选项

  •  1
  • knutter539  · 技术社区  · 6 年前

    我向数据库中添加了第二个表,其中包含我希望在组合框中看到的新列中datagrid的每一行的不同选项。每个选项都有一个与之关联的键,该键与我的主表中的一列相匹配,该列的值为0到8。我有两个问题,其中一个我已经解决了:

    1. 加载网格时,我希望组合框列显示与每行的[状态]键相对应的[描述]。这很有效。

    2. 我希望用户选择[描述]单元格,并用下拉菜单打开所有可能的[描述]选项,以便更改项目的状态。

    例如,如果某个组件处于保留状态,则用户需要在网格中选择该组件,并在状态列的下拉列表中选择“保留”。

    状态正确显示,但下拉列表中未填充CNCComponentStatus表中的8个选项。我敢打赌,我没有在SqlDataAdapter中正确地用第二个表填充数据集。我没有正确使用SelectedItem/ItemSource/SelectedValuePath。

    这是网格的截图 grid 这是我的数据结构 structure

    以下是状态选项: enter image description here

    以下是datagrid的xaml(仅适用于相关部分):

    <DataGrid Name="dataGrid1" ItemsSource="{Binding Path=test_3DimensionalDB}" AutoGenerateColumns="False">
    <DataGridTemplateColumn x:Name="StatusColumn" Header="Status" Width="*" IsReadOnly="False">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock x:Name="cboStatus" Text="{Binding Path=Description, Mode=TwoWay}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
                <ComboBox x:Name="StatusCombo" IsEditable="True" SelectedValuePath="{Binding Status}" DisplayMemberPath="{Binding Description}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
    

    下面是获取数据的方法:

     Private Sub SelectQuery(ByVal company As String, ByVal status As String, ByVal component As String)
    
        Dim com As String = "SELECT tmfCNCComponent_threed.[CNCComponentKey]
        ,tmfCNCComponent_threed.[CompanyID]
        ,tmfCNCComponent_threed.[JobNumber]
        ,tmfCNCComponent_threed.[LogNumber]
        ,tmfCNCComponent_threed.[Customer]
        ,tmfCNCComponent_threed.[DueDate]
        ,tmfCNCComponent_threed.[JobLeader]
        ,tmfCNCComponent_threed.[CADProgrammer]
        ,tmfCNCComponent_threed.[Salesperson]
        ,tmfCNCComponent_threed.[CNCProgrammer]
        ,tmfCNCComponent_threed.[ComponentDescription]
        ,tmfCNCComponent_threed.[ComponentFilePath]
        ,tmfCNCComponent_threed.[Material]
        ,tmfCNCComponent_threed.[ComponentSizeX]
        ,tmfCNCComponent_threed.[ComponentSizeY]
        ,tmfCNCComponent_threed.[ComponentSizeZ]
        ,tmfCNCComponent_threed.[QuantityShown]
        ,tmfCNCComponent_threed.[QuantityMirror]
        ,tmfCNCComponent_threed.[UpdateTime]
        ,tmfCNCComponent_threed.[Status]
        ,tmfCNCComponent_threed.[ProgStarted]
        ,tmfCNCComponentStatus_threed.[Description]
        FROM [test_3DimensionalDB].[dbo].[tmfCNCComponent_threed]
        INNER JOIN tmfCNCComponentStatus_threed
        ON tmfCNCComponent_threed.Status = tmfCNCComponentStatus_threed.CNCComponentStatusKey 
        WHERE [ComponentDescription] " & component & " 'trode%' AND [CompanyID]='" & company & "' AND [Status]" & status & "ORDER BY [UpdateTime] DESC"
    
        Dim Adpt As New SqlDataAdapter(com, con)
        con.Open()
        Dim ds As New DataSet()
        Adpt.Fill(ds, "dbo.tmfCNCComponent_threed")
    
        dataGrid1.ItemsSource = ds.Tables("dbo.tmfCNCComponent_threed").DefaultView
    
        con.Close()
    
        RowCount()
        searchBox.Clear()
    
    End Sub
    

    谢谢您的时间,很抱歉提供了太多的细节。

    编辑: 以下是我如何尝试填充组合框,因为我没有正确绑定。虽然我不太明白如何只显示一列而不是DefaultView。此外,“StatusCombo”由于其保护级别而无法访问?

        Dim com2 As String = "SELECT * FROM tmfCNCComponentStatus_threed"
        Dim AdptStatus As New SqlDataAdapter(com2, con)
        AdptStatus.Fill(ds, "dbo.tmfCNCComponentStatus_threed")
        StatusCombo.ItemsSource = ds.Tables("dbo.tmfCNCComponentStatus_threed").DefaultView
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   15ee8f99-57ff-4f92-890c-b56153    6 年前

    我想这个组合框最终应该是这样的。不需要x:Name属性。我也怀疑是否需要IsEditable。

    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox 
                IsEditable="True" 
                SelectedValuePath="Status" 
                DisplayMemberPath="Description" 
                SelectedValue="{Binding Status}"
                />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
    

    SelectedValuePath DisplayMemberPath 是字符串。它们是填充 ComboBox (如果使用常规C#类实例填充,则它们将成为item类的属性名称)。您试图将这些属性绑定到您没有的viewmodel的属性,但即使您有一个viewmodel,它也不会有这些属性。但是,绑定是什么以及它的作用的概念一开始可能会非常棘手。

    我差点告诉你 read the documentation on SelectedValuePath ,但文件已经修改,现在基本上没有意义了。 DisplayMemberPath is better

    第二:您应该有一个viewmodel。缺少viewmodel使一切变得更加困难。但您没有viewmodel。

    您需要做的是从数据库中获取所需内容,并将其放入某种集合中,以便组合框可以绑定到其中。

    由于缺少viewmodel作为该集合的自然家园,我们将通过在窗口的资源中创建CollectionViewSource来实现这一点。

    <Window
        x:Class="blah blah"
        ...stuff...
        >
        <Window.Resources>
            <CollectionViewSource
                x:Key="StatusItems"
                />
        </Window.Resources>
    

    我们将使用它来填充组合框,如下所示:

    <ComboBox 
        x:Name="StatusCombo" 
        SelectedValuePath="Status" 
        DisplayMemberPath="Description" 
        ItemsSource="{Binding Source={StaticResource StatusItems}}"
        />
    

    但我们的CollectionViewSource是空的。所以我们必须以某种方式填充它。每当您进行数据库查询时,我们都会这样做。

    Dim statusCVS As CollectionViewSource = FindResource("StatusItems")
    
    Dim com2 As String = "SELECT * FROM tmfCNCComponentStatus_threed"
    Dim AdptStatus As New SqlDataAdapter(com2, con)
    AdptStatus.Fill(ds, "dbo.tmfCNCComponentStatus_threed")
    
    Dim statusRows = ds.Tables("dbo.tmfCNCComponentStatus_threed").Rows
    Dim statuses As New List(Of Object)
    
    For Each row As DataRow In statusRows
        statuses.Add(New With {
                .Status = CInt(row("CNCComponentStatusKey")),
                .Description = CStr(row("Description"))
            })
    Next
    
    statusCVS.Source = statuses
    

    如果可行,这将比循环更好:

    Dim statuses = From row In ds.Tables("dbo.tmfCNCComponentStatus_threed")
                   .Rows.Cast(Of DataRow)
                   Select New With {
                        .Status = CInt(row("CNCComponentStatusKey")),
                        .Description = CStr(row("Description"))
                    }
    
    statusCVS.Source = statuses
    

    好了,现在我们有了这个部分:

        SelectedValue="{Binding Status}"
    

    我猜是吧 test_3DimensionalDB (您的DataGrid是否正在实际填充?)必须有一个列,它是组合中状态id值的外键,我猜它可能会被调用 Status

    所以我们想做的是:假设你有两个项目:

    item 0:
        Status = 1
        Description = Dog
    item 1:
        Status = 2
        Description = Cat
    

    DisplayMemberPath="Description" 表示项目0将显示为“Dog”,即其Description属性的值。出于同样的原因,项目1将显示为“Cat”。

    SelectedValuePath="Status" 意味着当绑定将SelectedValue设置为 2 ,组合框将查看其items集合,以找到具有 地位 属性等于 2. ,然后选择该项目。如果我们设置 SelectedValuePath="Fred" ,它将查找具有名为 Fred 2.

    同样,如果用户自己更改了选择,则会转到另一个方向:假设用户选择了项0,因此组合框会参考自己的 SelectedValuePath ,查看“状态”,并获取 地位 所选项目的属性值(如果有)。对于项目0,这是 1 。然后组合框将为 1. 自己的 SelectedValue 所有物

    上的绑定 选定值 然后将收到通知 选定值 已更改,它将获取新值并更新绑定到的数据库行列(在本例中也称为“Status”)。

    这个 Binding 是一个粘在周围做事情的物体。这不是“任务”的花哨词。

    SelectedValue="{Binding Status}"