将附加列与数据网格 WPF 中的任何控件绑定
Binding additional column with any control in datagrid WPF
我有一项要求使用 WPF C# 在数据网格内的“listview”或“datagrid”中绑定附加列。
我的基本数据网格如下
<table border="1" width="100%">
<tr>
<td>Item Id</td>
<td>Item Name</td>
<td>Quantity</td>
<td>Price</td>
</tr>
<tr>
<td>500</td>
<td>Sanwich</td>
<td>2</td>
<td>10</td>
</tr>
</table>
以上datagrid
我的XAML
代码如下
<DataGrid Grid.Column="1" Margin="8,60,8,16"AutoGenerateColumns="False" Height="350"
HorizontalAlignment="Left" Name="gridOrderDetails" VerticalAlignment="Top" Width="450" >
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding itemId}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding comments}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding ItemPrice}" />
</DataGrid.Columns>
</DataGrid>
我的代码隐藏在按钮点击事件中的代码如下:
private void Button_Click(object sender, RoutedEventArgs e)
{
try
{
DBDataContext dbContext = new DBDataContext();
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
gridOrderDetails.ItemsSource = dbContext.SP_Get_ItemList(orderRow.orderid);
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
return;
}
}
我想要的输出如下
<table border="1" width="100%">
<tr>
<td>Item Id</td>
<td>Item Name</td>
<td>Additionals</td>
<td>Quantity</td>
<td>Price</td>
</tr>
<tr>
<td>500</td>
<td>Sanwich</td>
<td>Egg<p class="MsoNormal" style="margin-left:0in">Ketchup</p>
<p>
<span style="font-size: 11.0pt; line-height: 115%; font-family: Calibri,sans-serif">
Salad</span></td>
<td>2</td>
<td>10</td>
</tr>
</table>
为了实现这个 datagrid
我使用 DataGridTemplateColumn
.
编写了我的 XAML
代码如下
<DataGrid Grid.Column="1" Margin="8,60,8,16"AutoGenerateColumns="False" Height="350"
HorizontalAlignment="Left" Name="gridOrderDetails" VerticalAlignment="Top" Width="450" LoadingRow="gridOrderDetails_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding itemId}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" />
<DataGridTemplateColumn Header="Addtionals">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid AutoGenerateColumns="False" Name="gridAdditionals" >
<DataGridTextColumn Header="Additional" Binding="Additionals"></DataGridTextColumn>
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
<DataGridTextColumn Header="Comments" Binding="{Binding comments}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding ItemPrice}" />
</DataGrid.Columns>
</DataGrid>
在后面的代码中,我尝试使用 LoadingRow
事件,但无法从单元格值传递相应的 ItemID
。
private void gridOrderDetails_LoadingRow(object sender, DataGridRowEventArgs e)
{
DCAPPDBDataContext dbContext = new DCAPPDBDataContext();
DataGrid grid = FindChild<DataGrid>(gridOrderDetails, "gridAdditionals");
grid.ItemsSource = dbContext.SP_Get_AdditionalsList(500);
}
我猜我使用的逻辑是错误的。这可以使用 Asp.net C# 中的 ItemDataBound
来实现。
任何人都可以帮助我如何在 WPF C# 中执行此操作。
使用 WPF
时,应遵循 MVVM
模式。无论哪种方式,您都应该为 Order
(包含 Id、Name、Quantity 等属性)定义一个合适的 class(即视图模型)。此 class 还应该有一个 属性 用于您的 Aditionals
(例如 strings
的集合)。然后通过使用适当的 DataBindings
您将实现您想要的功能。
这是一个可以给您提供思路的工作示例:
订单class:
public class Order : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public Order(int id)
{
DBDataContext dbContext = new DBDataContext();
DCAPPDBDataContext dbContext2 = new DCAPPDBDataContext();
var itemsSource = dbContext.SP_Get_ItemList(id);
var additionals = dbContext2.SP_Get_AdditionalsList(id);
Id = id;
Name = itemsSource.name;
Quantity = itemsSource.quantity;
// other properties ...
Additionals = new ObservableCollection<string>();
foreach (var item in additionals)
{
Additionals.Add(item);
}
}
private int _id;
public int Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
// define other properties e.g. Name, Quantity, Price, etc.
// the same way as Id.
public ObservableCollection<string> Additionals {get;set;}
}
Xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" AutoGenerateColumns="False"
ItemsSource="{Binding Orders}"
SelectedItem="{Binding SelectedOrder}">
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding Id}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Addtionals">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Additionals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
<Button Grid.Row="1" Content="New Order" Click="Order_Click"/>
</Grid>
MainWindow.cs:
public ObservableCollection<Order> Orders { get; set; }
public Order SelectedOrder { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Orders = new ObservableCollection<Order>();
}
private void Order_Click(object sender, RoutedEventArgs e)
{
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
Orders.Add(new Order(orderRow.orderid));
}
在 Bahman_Aries post 和一些小东西的帮助下,我正在 post 找到精确的解决方案。
这是我想要的精确解决方案。
订单class:
public class Order : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public Order(SP_Get_ItemListResult itemResult)
{
DBDataContext dbContext = new DBDataContext();
orderItemID = itemResult.orderItemID;
itemName = itemResult.ItemName;
quantity = itemResult.quantity;
// other properties ...
var additionals = dbContext.SP_Get_AdditionalsList(orderItemID);
Additionals = new ObservableCollection<string>();
foreach (var item in additionals)
{
Additionals.Add(item.Additionals);
}
}
private int _id;
public int Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
// define other properties e.g. Name, Quantity, Price, etc.
// the same way as Id.
public ObservableCollection<string> Additionals {get;set;}
}
XAML 代码无变化。
MainWindow.cs:
public ObservableCollection<Order> Orders { get; set; }
public Order SelectedOrder { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Orders = new ObservableCollection<Order>();
}
private void Order_Click(object sender, RoutedEventArgs e)
{
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
List<SP_Get_ItemListResult> itemsSource = dbContext.SP_Get_ItemList(orderRow.orderid).ToList();
for (int i = 0; i < itemsSource.Count(); i++)
{
Orders.Add(new Order(itemsSource[i]));
}
}
我有一项要求使用 WPF C# 在数据网格内的“listview”或“datagrid”中绑定附加列。
我的基本数据网格如下
<table border="1" width="100%">
<tr>
<td>Item Id</td>
<td>Item Name</td>
<td>Quantity</td>
<td>Price</td>
</tr>
<tr>
<td>500</td>
<td>Sanwich</td>
<td>2</td>
<td>10</td>
</tr>
</table>
以上datagrid
我的XAML
代码如下
<DataGrid Grid.Column="1" Margin="8,60,8,16"AutoGenerateColumns="False" Height="350"
HorizontalAlignment="Left" Name="gridOrderDetails" VerticalAlignment="Top" Width="450" >
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding itemId}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding comments}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding ItemPrice}" />
</DataGrid.Columns>
</DataGrid>
我的代码隐藏在按钮点击事件中的代码如下:
private void Button_Click(object sender, RoutedEventArgs e)
{
try
{
DBDataContext dbContext = new DBDataContext();
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
gridOrderDetails.ItemsSource = dbContext.SP_Get_ItemList(orderRow.orderid);
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
return;
}
}
我想要的输出如下
<table border="1" width="100%">
<tr>
<td>Item Id</td>
<td>Item Name</td>
<td>Additionals</td>
<td>Quantity</td>
<td>Price</td>
</tr>
<tr>
<td>500</td>
<td>Sanwich</td>
<td>Egg<p class="MsoNormal" style="margin-left:0in">Ketchup</p>
<p>
<span style="font-size: 11.0pt; line-height: 115%; font-family: Calibri,sans-serif">
Salad</span></td>
<td>2</td>
<td>10</td>
</tr>
</table>
为了实现这个 datagrid
我使用 DataGridTemplateColumn
.
XAML
代码如下
<DataGrid Grid.Column="1" Margin="8,60,8,16"AutoGenerateColumns="False" Height="350"
HorizontalAlignment="Left" Name="gridOrderDetails" VerticalAlignment="Top" Width="450" LoadingRow="gridOrderDetails_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding itemId}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" />
<DataGridTemplateColumn Header="Addtionals">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid AutoGenerateColumns="False" Name="gridAdditionals" >
<DataGridTextColumn Header="Additional" Binding="Additionals"></DataGridTextColumn>
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
<DataGridTextColumn Header="Comments" Binding="{Binding comments}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding ItemPrice}" />
</DataGrid.Columns>
</DataGrid>
在后面的代码中,我尝试使用 LoadingRow
事件,但无法从单元格值传递相应的 ItemID
。
private void gridOrderDetails_LoadingRow(object sender, DataGridRowEventArgs e)
{
DCAPPDBDataContext dbContext = new DCAPPDBDataContext();
DataGrid grid = FindChild<DataGrid>(gridOrderDetails, "gridAdditionals");
grid.ItemsSource = dbContext.SP_Get_AdditionalsList(500);
}
我猜我使用的逻辑是错误的。这可以使用 Asp.net C# 中的 ItemDataBound
来实现。
任何人都可以帮助我如何在 WPF C# 中执行此操作。
使用 WPF
时,应遵循 MVVM
模式。无论哪种方式,您都应该为 Order
(包含 Id、Name、Quantity 等属性)定义一个合适的 class(即视图模型)。此 class 还应该有一个 属性 用于您的 Aditionals
(例如 strings
的集合)。然后通过使用适当的 DataBindings
您将实现您想要的功能。
这是一个可以给您提供思路的工作示例:
订单class:
public class Order : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public Order(int id)
{
DBDataContext dbContext = new DBDataContext();
DCAPPDBDataContext dbContext2 = new DCAPPDBDataContext();
var itemsSource = dbContext.SP_Get_ItemList(id);
var additionals = dbContext2.SP_Get_AdditionalsList(id);
Id = id;
Name = itemsSource.name;
Quantity = itemsSource.quantity;
// other properties ...
Additionals = new ObservableCollection<string>();
foreach (var item in additionals)
{
Additionals.Add(item);
}
}
private int _id;
public int Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
// define other properties e.g. Name, Quantity, Price, etc.
// the same way as Id.
public ObservableCollection<string> Additionals {get;set;}
}
Xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" AutoGenerateColumns="False"
ItemsSource="{Binding Orders}"
SelectedItem="{Binding SelectedOrder}">
<DataGrid.Columns>
<DataGridTextColumn Header="Item ID" Binding="{Binding Id}" />
<DataGridTextColumn Header="Item Name" Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Addtionals">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Additionals}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
<DataGridTextColumn Header="Item Price" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
<Button Grid.Row="1" Content="New Order" Click="Order_Click"/>
</Grid>
MainWindow.cs:
public ObservableCollection<Order> Orders { get; set; }
public Order SelectedOrder { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Orders = new ObservableCollection<Order>();
}
private void Order_Click(object sender, RoutedEventArgs e)
{
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
Orders.Add(new Order(orderRow.orderid));
}
在 Bahman_Aries post 和一些小东西的帮助下,我正在 post 找到精确的解决方案。 这是我想要的精确解决方案。
订单class:
public class Order : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public Order(SP_Get_ItemListResult itemResult)
{
DBDataContext dbContext = new DBDataContext();
orderItemID = itemResult.orderItemID;
itemName = itemResult.ItemName;
quantity = itemResult.quantity;
// other properties ...
var additionals = dbContext.SP_Get_AdditionalsList(orderItemID);
Additionals = new ObservableCollection<string>();
foreach (var item in additionals)
{
Additionals.Add(item.Additionals);
}
}
private int _id;
public int Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("Id");
}
}
// define other properties e.g. Name, Quantity, Price, etc.
// the same way as Id.
public ObservableCollection<string> Additionals {get;set;}
}
XAML 代码无变化。
MainWindow.cs:
public ObservableCollection<Order> Orders { get; set; }
public Order SelectedOrder { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Orders = new ObservableCollection<Order>();
}
private void Order_Click(object sender, RoutedEventArgs e)
{
SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;
List<SP_Get_ItemListResult> itemsSource = dbContext.SP_Get_ItemList(orderRow.orderid).ToList();
for (int i = 0; i < itemsSource.Count(); i++)
{
Orders.Add(new Order(itemsSource[i]));
}
}