C# 访问DataGrid中列的组件

C# 访问DataGrid中列的组件,c#,wpf,xaml,datagrid,integerupdown,C#,Wpf,Xaml,Datagrid,Integerupdown,我是一名Java开发人员,在.NET中作为一个试点项目被分配了一些任务 这是一个需要使用WPF和EntityFramework开发的小型发票应用程序 我的任务之一是在窗口中显示发票列表,单击任何发票的“编辑”后,我应显示该发票的详细信息以及分配给该发票的发票项目 下面是显示发票项目的XAML代码片段 <DataGrid x:Name="ProductGrid" AutoGenerateColumns="False" HorizontalAlignment="Stretch"

我是一名Java开发人员,在.NET中作为一个试点项目被分配了一些任务

这是一个需要使用WPF和EntityFramework开发的小型发票应用程序

我的任务之一是在窗口中显示发票列表,单击任何发票的“编辑”后,我应显示该发票的详细信息以及分配给该发票的发票项目

下面是显示发票项目的XAML代码片段

<DataGrid x:Name="ProductGrid" AutoGenerateColumns="False" HorizontalAlignment="Stretch" 
            HorizontalContentAlignment="Stretch" ColumnWidth="*" Height="464" VerticalAlignment="Top" Margin="444,16,10,0" CanUserAddRows="false">
    <DataGrid.Columns>
        <DataGridTemplateColumn Width="55" Header="Selected">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox Margin="2,0,2,0" HorizontalAlignment="Center" VerticalAlignment="Center" 
                                Checked="Product_Selected" Unchecked="Product_Deselected" IsChecked="{Binding Path=selected}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Width="60" Header="Quantity">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <xctk:IntegerUpDown x:Name="UPDOWN" Increment="1" Minimum="0" HorizontalAlignment="Center" ValueChanged="Quantity_Changed" 
                                        VerticalAlignment="Center" Width="50" Value="{Binding productQuantity, Mode=TwoWay}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="Product Name" Width="250" Binding="{Binding Path=productName}"/>
        <DataGridTextColumn Header="Weight" Binding="{Binding Path=productWeight}"/>
        <DataGridTextColumn Header="Size" Binding="{Binding Path=productSize}"/>
        <DataGridTextColumn Header="Sale price" Binding="{Binding Path=productSalePrice}"/>
    </DataGrid.Columns>
</DataGrid>
为此,我需要访问所选行的IntegerUpDown组件。不幸的是,我不知道该怎么做

我希望你们中的一些.NET天才能够在这件事上帮助我

非常感谢

里根,
阿塞拉。

好吧,我已经有一段时间没有回答这里的任何问题了,但你的问题绝对值得关注

首先,关于这一点:

我的职业是Java开发人员

忘记java。

您在java中可能使用的大多数(如果不是全部的话)模式和范例(相当繁琐且过于冗长)在C#和WPF中几乎没有用处

这是因为,与java相比,C#是一种现代的、专业级的语言,具有许多易于开发和大大减少样板文件的语言特性

除此之外,WPF是一个高级、专业级别的UI框架,具有大量高级功能(最显著的是和),允许您创建高级抽象,并将代码和应用程序逻辑与UI组件完全分离,在不引入讨厌的结构或不必要的耦合的情况下实现最大的灵活性

这种抽象是通过实现一个名为的模式来实现的。这种模式在大多数(如果不是全部的话)现代UI技术中非常普遍,包括Web和非Web,但java世界除外,java世界似乎相信(毫不奇怪)现在仍然是1990年

因此,我建议您花点时间去理解和接受,而不是试图从遗留技术中锤炼概念,使它们以某种方式适合WPF

现在,我看到您的代码中存在一些缺陷,无论是从代码本身还是从您编写代码的理念/方法来看

首先,在XAML中出现诸如
Height=“464”Margin=“444,16,10,0”之类的东西表明您使用了Visual Studio designer来构建这样的UI。作为学习练习,这是很有用的,但出于上述原因,对于生产代码来说,这是非常不鼓励的

我建议您花点时间正确地学习XAML,并了解WPF布局系统是如何工作的,以及如何编写独立于分辨率、自动可调的WPF UI,而不是固定大小、固定位置的布局,这些布局即使在调整包含窗口的大小时也无法正确调整

同样,当来自任何其他技术时,开发人员在WPF中犯的典型错误是如何处理事情,而不是如何编写代码。让我们分析一下您的代码:

 var currRow = ProductGrid.CurrentItem; // Current row

 InvoiceItemsDTO sel = (InvoiceItemsDTO)currRow; // Current row DTO OBJECT

 if (sel != null)
 {
    //...
 }
乍一看,这段代码(除了可以缩短之外)还不错。您正在检索底层数据对象,而不是试图弄乱UI元素。这是WPF中的正确方法。您需要操作数据项,而不是用户界面

让我们把它改写成更像C的方式:

var row = ProductGrid.CurrentItem as InvoiceItemsDTO;
if (row != null)
{
   //...
}
注意:上面的代码展示了一个示例,说明了C语言级功能(在本例中,是)如何帮助简化样板文件(我们现在有2行代码,而不是3行代码),允许在java等劣质技术中使用漂亮的代码

好的,到目前为止还不错,但是你从以数据为中心的思维中溜走了,转而尝试出于某种原因操纵UI

想想看:您正在尝试“更新与当前选定行相对应的
IntegerUpDown
属性的
值”

但是,您的XAML显示,
IntegerUpDown
属性实际上是通过双向数据绑定绑定到底层数据项中名为
productQuantity
的属性

因此,基本上,您的代码会产生如下结果:

get Data Item -> get UI item -> update UI item -> DataBinding updates Data Item.
看到了吗?您正在创建一个完全不必要的间接过程。相反,只需对数据项而不是UI进行操作,并让双向数据绑定处理其余部分。这就是WPF的心态

var row = ProductGrid.CurrentItem as InvoiceItemsDTO;
if (row != null)
{
    row.productQuantity++;
}
看看当你与现代科技打交道时,生活有多轻松

但它甚至还没有结束

您的XAML还显示您正在处理的
复选框
已将其
选中
属性绑定到基础数据项中名为
的属性

<CheckBox [...] IsChecked="{Binding Path=selected}"/>
另外,注意使用合适的套管。camelCasing非常可怕,因此只能在C#中为
private
成员保留。不是公共的

看到了吗?简单、干净、可测试且美观,而且它可以正常工作

但是,它是如何工作的

1-当用户单击复选框时,IsChecked值将更新

2-WPF的数据绑定将
InvoiceItemsDTO.Selected
属性的值更新为
true

3-您的代码将+1添加到
ProductQuantity
属性中

4-WPF的数据绑定反映了用户界面中的
ProductQuantity
更改,前提是您已正确绑定

取消选中复选框时会出现相同的工作流,但值为
false

这消除了对事件处理程序、强制转换、代码隐藏和其他繁琐方法的需求,这些方法需要无用的样板文件,并引入不必要的、不希望的耦合

底线:<CheckBox [...] IsChecked="{Binding Path=selected}"/>
public class InvoiceItemsDTO
{
    private bool _selected;
    public bool Selected
    {
        get { return _selected; }
        set 
        {
            _selected = value;

            //This is where your code should be.
            if (value)
               ProductQuantity++;
            else
               ProductQuantity--;
        }
    }
}