【问题标题】:WPF DataGrid Question - Referencing TextBox inside RowDetailsTemplateWPF DataGrid 问题 - 在 RowDetailsTemplate 中引用文本框
【发布时间】:2021-09-20 14:42:59
【问题描述】:

经过数小时的研究如何做到这一点,我很困惑,需要堆栈溢出专家的帮助。我不是 WPF 开发人员,周一才开始自学,所以请耐心等待 - 但我需要创建一个用户界面以允许最终用户更新 MS SQL 表中的一些字段。我使用此应用程序的目标是将存储过程的结果显示到数据网格中,允许最终用户选择一行,使用 RowDetailsTemplate 为他们提供该记录的完整详细信息。在该插图中,我想让他们能够执行几个操作 1)更新表中的单个列,可能通过调用存储过程和 2)有一个按钮,可能通过调用存储过程来执行另一个操作,传入行的唯一 ID。

我遇到的问题是我不确定如何 1) 从所选行中引用 TextBox。找不到文本框的名称。 2)我不确定如何在后面的代码中引用所选行的绑定唯一标识符(“发票号”)。

这基本上是我的应用的样子。您可以看到我在行详细信息中有两个小表单,更新状态和电子邮件客户端。

这是生成它的 XAML 代码:

<Page x:Class="WpfApp1.Page3"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:controls="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
  xmlns:local="clr-namespace:WpfApp1" 
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800"
  Title="Page3">

<Grid Background="#FFDEDEDE">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20" />     <!--0 Left Margin-->
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="50"  />      <!--0 Green Button Bar-->
        <RowDefinition Height="auto" />     <!--1 Title Row-->
        <RowDefinition Height="auto" />     <!--2 Report Buttons-->
        <RowDefinition Height="10" />       <!--3 Buffer-->
        <RowDefinition Height="*" />        <!--4 Table-->
        <RowDefinition Height="20" />       <!--5 Bottom Margin-->
    </Grid.RowDefinitions>

    <Border Background="#4a9463" Grid.Row="0" Grid.ColumnSpan="6"/>
    <Button x:Name="BackButton" Grid.Column="3" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center" Content="Back to Home" Click="BackButton_Click" />

    <TextBlock Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" FontSize="20" Text="DH Approvals Automation (TEST)" Margin="0,0,0,10"/>
    
    <WrapPanel Grid.Column="1" Grid.Row="2">
        <TextBlock Text="Date Loaded: " VerticalAlignment="Bottom" />
        <DatePicker x:Name="DateLoaded" />
    </WrapPanel>
    

    <Button x:Name="DispData" Grid.Column="3" Grid.Row="2" HorizontalAlignment="Right" Width="100" Content="Display" Click="DispData_Click"/>



    <controls:DataGrid Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="3" 
                       x:Name="PermInvoices" 
                       AutoGenerateColumns="False"
                       AlternatingRowBackground="#FFE2F9D8"
                       ItemsSource="{Binding}"
                       CanUserResizeRows="False"
                       CanUserAddRows="False"
                       FrozenColumnCount="2" 
                       AreRowDetailsFrozen="True"
                        >
        <controls:DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="10" />
                        <ColumnDefinition Width="300" />
                        <ColumnDefinition Width="300" />
                        <ColumnDefinition Width="300" />
                        <ColumnDefinition Width="300" />
                        <ColumnDefinition Width="10" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="10"  />
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="10" />
                    </Grid.RowDefinitions>

                    <TextBlock Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="3" FontWeight="Bold" Text="Invoice Details:" />

                    <StackPanel Grid.Column="1" Grid.Row="2">
                        <WrapPanel>
                            <TextBlock Text="Invoice #: " FontWeight="Bold"/>
                            <TextBlock Text="{Binding Path=[Invoice Number]}" />
                        </WrapPanel>
                        <WrapPanel>
                            <TextBlock Text="Job #: " FontWeight="Bold"/>
                            <TextBlock Text="{Binding Path=[Job Number]}" />
                        </WrapPanel>
                        <WrapPanel>
                            <TextBlock Text="Candidate Name: " FontWeight="Bold"/>
                            <TextBlock Text="{Binding Path=[First Name]}" />
                            <TextBlock Text=" "/>
                            <TextBlock Text="{Binding Path=[Last Name]}" />
                        </WrapPanel>
                        
                    </StackPanel>
                    
                    <StackPanel Grid.Column="2" Grid.Row="2">
                        <TextBlock Text="Approver Emails: " FontWeight="Bold"/>
                        <TextBlock Text="{Binding Path=[Sales Person Emails]}" />
                    </StackPanel>

                    <StackPanel Grid.Column="3" Grid.Row="2">
                        <TextBlock Text="Billing Contact Emails: " FontWeight="Bold"/>
                        <TextBlock Text="{Binding Path=[Billing Emails]}" />
                    </StackPanel>

                    <StackPanel Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="3">
                        <TextBlock Text="Bullhorn Comments: " FontWeight="Bold"/>
                        <TextBlock Text="{Binding Path=[BHcomments]}" />
                    </StackPanel>

                    <StackPanel Grid.Column="4" Grid.Row="2" Background="#FF7C7C7C" Margin="0,0,0,20">
                        <TextBlock Text="Invoice Status: " FontWeight="Bold" Margin="10"/>
                        <TextBox Name="StatusTxt" Text="{Binding Path=[status]}"  Margin="10"/>
                        <Button Content="Update Status" x:Name="UpdateStatusbtn" Click="UpdateStatusbtn_Click" Margin="10"/>
                    </StackPanel>

                    
                    <Button Grid.Column="4" Grid.Row="3" Margin="10" Height="30" VerticalAlignment="Top" Content="Email Client" x:Name="EmailClientbtn" Click="EmailClientbtn_Click"/>
                    


                </Grid>
            </DataTemplate>
        </controls:DataGrid.RowDetailsTemplate>

        <controls:DataGrid.Columns>
            <controls:DataGridTextColumn Header="Job Number" Binding="{Binding Path=[Job Number]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Address Code" Binding="{Binding Path=[Address Code]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="First Name" Binding="{Binding Path=[First Name]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Last Name" Binding="{Binding Path=[Last Name]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Start Date" Binding="{Binding Path=[Start Date], StringFormat=d}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="SBU" Binding="{Binding Path=SBU}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Office" Binding="{Binding Path=Office}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Document Date" Binding="{Binding Path=[Document Date], StringFormat=d}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Invoiced Date" Binding="{Binding Path=[Invoiced Date], StringFormat=d}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Position" Binding="{Binding Path=Position}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Invoice Number" Binding="{Binding Path=[Invoice Number]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Orig TRX Amount" Binding="{Binding Path=[Original TRX Amount], StringFormat=C}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Current TRX Amount" Binding="{Binding Path=[Current TRX Amount], StringFormat=C}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Status" Binding="{Binding Path=status}"/>
            <controls:DataGridTextColumn Header="BH Comments" Binding="{Binding Path=BHcomments}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Billing Emails" Binding="{Binding Path=[Billing Emails]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Customer Number" Binding="{Binding Path=[Customer Number]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Customer Name" Binding="{Binding Path=[Customer Name]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Tax Schedule ID" Binding="{Binding Path=[Tax Schedule ID]}" IsReadOnly="True"/>
            <controls:DataGridTextColumn Header="Sales Person Emails" Binding="{Binding Path=[Sales Person Emails]}" IsReadOnly="True"/>
        </controls:DataGrid.Columns>
    </controls:DataGrid>




</Grid>
</Page>

最后,这里是 C# 代码。我有来自 RowDetailsTemplate 的两个按钮的类,但只是不知道如何引用所选行的 TextBox 或“发票编号”的绑定数据。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;

namespace WpfApp1
{
/// <summary>
/// Interaction logic for Page3.xaml
/// </summary>
public partial class Page3 : Page
{
    

    public Page3()
    {
        InitializeComponent();
        DateLoaded.SelectedDate = DateTime.Today;
        
    }
    private void BackButton_Click(object sender, RoutedEventArgs e)
    {
        this.NavigationService.Navigate(new Uri("Page1.xaml", UriKind.Relative));
    }


    private void DispData_Click(object sender, RoutedEventArgs e)
    {
        DateTime? SelectedDate = DateLoaded.SelectedDate;
        string sDateLoaded = SelectedDate.Value.ToString("MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture);

        string ConString = ConfigurationManager.ConnectionStrings["PlacementInvoices"].ConnectionString;
        string CmdString = string.Empty;


        CmdString = "exec ssrs_DHAutomationLog @dateloaded"; 
        
        try
        {
            using (SqlConnection con = new SqlConnection(ConString))
            {
                SqlCommand cmd = new SqlCommand(CmdString, con);
                cmd.Parameters.Add("@dateloaded", sDateLoaded);
                SqlDataAdapter sda = new SqlDataAdapter(cmd);
                DataTable dt = new DataTable("Invoices");
                sda.Fill(dt);
                PermInvoices.ItemsSource = dt.DefaultView;
            }

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private void UpdateStatusbtn_Click(object sender, RoutedEventArgs e)
    {
        //This is where I just can't figure out how to select the TextBox from the selected row.  And how to pull the "Invoice Number" value from that row.
        string newStatus = StatusTxt.value;
    }

    private void EmailClientbtn_Click(object sender, RoutedEventArgs e)
    {
        //This is where I can't figure out how to pull the "Invoice Number" from the selected row.
        MessageBox.Show("Doesn't Work Yet.");
    }

}

提前感谢您的帮助。我进行了深入研究,但肯定不知道正确的关键字。

【问题讨论】:

    标签: sql wpf windows data-binding datagrid


    【解决方案1】:

    您可以使用以下代码。我在UpdateStatusbtn_Click 事件中检索到了newStatusInvoiceNumber

    EmailClientbtn_Click 事件中,我刚刚获得了InvoiceNumber 的值。

    UpdateStatusbtn_Click 事件

    private void UpdateStatusbtn_Click(object sender, RoutedEventArgs e)
    {
        DataGridRow PermInvoicesRow = (DataGridRow)(PermInvoices.ItemContainerGenerator.ContainerFromItem(PermInvoices.SelectedItem));
        if (PermInvoicesRow == null) return;
    
        DataRowView rowSelected = (DataRowView)PermInvoicesRow.Item;
        DataGridDetailsPresenter PermInvoicesPresenter = FindVisualChild<DataGridDetailsPresenter>(PermInvoicesRow);
    
       DataTemplate template = PermInvoicesPresenter.ContentTemplate;
       TextBox textBox = (TextBox)template.FindName("StatusTxt", PermInvoicesPresenter);
    
       //get newStatus form StatusTxt
       string newStatus = textBox.Text;
                
    
             
       //get InvoiceNumber 
       int InvoiceNumber = 0;
       if (rowSelected != null)
       {
           InvoiceNumber = (int)rowSelected.Row["InvoiceNumber"];
       }
    }
    

    EmailClientbtn_Click 事件

    private void EmailClientbtn_Click(object sender, RoutedEventArgs e)
    {
        DataGridRow PermInvoicesRow = (DataGridRow)(PermInvoices.ItemContainerGenerator.ContainerFromItem(PermInvoices.SelectedItem));
        if (PermInvoicesRow == null) return;
    
        DataRowView rowSelected = (DataRowView)PermInvoicesRow.Item;
               
        int InvoiceNumber = 0;
        if (rowSelected != null)
        {
           InvoiceNumber = (int)rowSelected.Row["InvoiceNumber"];
        }
    }
    

    FindVisualChild 方法

    public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
    {
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
       {
           DependencyObject child = VisualTreeHelper.GetChild(obj, i);
           if (child != null && child is T)
              return (T)child;
           else
           {
               T childOfChild = FindVisualChild<T>(child);
               if (childOfChild != null)
                  return childOfChild;
           }
       }
       return null;
     }
    

    【讨论】:

    • 您先生,是我的英雄。我能够对其进行调整以显示它根据需要捕获发票编号。谢谢!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-06-24
    • 2011-03-13
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 2013-12-22
    • 2021-10-24
    • 2010-11-02
    相关资源
    最近更新 更多