C# 访问DataGrid中列的组件
我是一名Java开发人员,在.NET中作为一个试点项目被分配了一些任务 这是一个需要使用WPF和EntityFramework开发的小型发票应用程序 我的任务之一是在窗口中显示发票列表,单击任何发票的“编辑”后,我应显示该发票的详细信息以及分配给该发票的发票项目 下面是显示发票项目的XAML代码片段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"
<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--;
}
}
}