On Binding DataGrid in WPF. No Content is getting Visible. Only Rows are getting created
I binded my DataGrid in Wpf with a datatable. But no data is getting visible to me. I can see three rows being created in the grid in the UI but data is not getting visible. I tried to change forecolor and backcolor as well. I dont know why this is happening.
Any help will be appreciable.
My Code
Code Behind
I tried this way
dt.AsEnumerable().ToList().ForEach(i => dgvSummary.Items.Add(i));
and also
dgvSummary.ItemsSource = dt.AsEnumerable().ToList();
XAML file
<my:DataGrid xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit"
Name="dgvSummary" ItemsSource="{Binding}" Grid.Row="1"
MinWidth="520" Height="180" HorizontalAlignment="Left"
FontSize="10" Background="#FFFEEFC8"
AutoGenerateColumns="False" SelectionUnit="Cell"
SelectionMode="Single" 开发者_StackOverflow中文版 RowBackground="Transparent">
<my:DataGrid.Columns>
<my:DataGridTemplateColumn Header="First Name"
IsReadOnly="True">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Visibility="Visible"
Foreground="Red"
Background="Transparent"
Text="{Binding Path=First_Name}"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn Header="Last Name"
IsReadOnly="True">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Foreground="Black"
Text="{Binding Path=LAST_NAME}"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
</my:DataGrid>
Try having a look at the output window during debugging - it will tell you if you have any binding errors.
I needed to solve this same issue and worked out examples where:
- The
DataGrid
is created in XAML - The
DataGrid
is created in C# (code-behind)
For (1) I needed to set DataGrid.ItemsSource = "{Binding}"
in XAML and then in C# to set DataGrid.DataContext
to a DataSet
For (2) the approach of (1) didn't work. Instead I skipped setting a DataGrid.DataContext
and set DataGrid.ItemsSource = DataTable.DefaultView
. No DataSet
was needed.
Here's a full working example of both:
MainWindow.xaml
<Window x:Class="DataGridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<Button Content="Run1" Width="100" Click="RunGrid1_Click"></Button>
<Button Content="Run2" Width="100" Click="RunGrid2_Click"></Button>
</StackPanel>
<ScrollViewer Name="sv1" Grid.Row="1">
<DataGrid Name="dg1" ItemsSource="{Binding}"></DataGrid>
</ScrollViewer>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Collections.ObjectModel;
using System.Data;
using System.Management.Automation;
//C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll
namespace DataGridTest
{
public partial class MainWindow : Window
{
string scriptText = @"$quotastat = @()
$quotastat += new-object psobject -property @{
Identity = 1
Value = '0.5GB'
IssueWarningQuota = '471860 KB'
ProhibitSendQuota = '498074 KB'
ProhibitSendReceiveQuota = '524288 KB'
}
$quotastat += new-object psobject -property @{
Identity = 2
Value = '1GB (default)'
IssueWarningQuota = '943719 KB'
ProhibitSendQuota = '996148 KB'
ProhibitSendReceiveQuota = '1048576 KB'
}
$quotastat";
public MainWindow()
{
InitializeComponent();
}
private void RunGrid1_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
PowerShell psExec = PowerShell.Create();
psExec.AddScript(scriptText);
Collection<PSObject> results;
Collection<ErrorRecord> errors;
results = psExec.Invoke();
errors = psExec.Streams.Error.ReadAll();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
foreach (PSMemberInfo member in results[0].Members)
{
if (member.MemberType == PSMemberTypes.NoteProperty)
{
dt.Columns.Add(member.Name, Type.GetType(member.TypeNameOfValue));
}
}
foreach (PSObject result in results)
{
DataRow dr = dt.NewRow();
foreach (PSPropertyInfo pi in result.Properties)
{
dr[pi.Name] = pi.Value;
}
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
dg1.DataContext = ds.Tables[0];
}
private void RunGrid2_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
PowerShell psExec = PowerShell.Create();
psExec.AddScript(scriptText);
Collection<PSObject> results;
Collection<ErrorRecord> errors;
results = psExec.Invoke();
errors = psExec.Streams.Error.ReadAll();
DataGrid outputGrid = new DataGrid()
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
};
DataTable dt = new DataTable();
foreach (PSMemberInfo member in results[0].Members)
{
if (member.MemberType == PSMemberTypes.NoteProperty)
{
dt.Columns.Add(member.Name, Type.GetType(member.TypeNameOfValue));
}
}
foreach (PSObject result in results)
{
DataRow dr = dt.NewRow();
foreach (PSPropertyInfo pi in result.Properties)
{
dr[pi.Name] = pi.Value;
}
dt.Rows.Add(dr);
}
outputGrid.ItemsSource = dt.DefaultView;
sv1.Content = outputGrid;
}
}
}
It doesn't work, because when you say
dgvSummary.ItemsSource = dt.AsEnumerable().ToList();
you are binding to IEnumerable<DataRow>. But DataRow doesn't have properties that you are trying to bind cells to, such as First_Name, Last_Name. You need to use indexer syntax to bind to DataRow fields, like this:
<TextBlock Visibility="Visible" Foreground="Red" Background="Transparent" Text="{Binding Path=[First_Name]}"/>
The reason why it works for dt.DefaultView is because DataView implements IBindingListView and ITypedList, and DataGrid can interogate these interfaces and resolve property names when it's binding.
精彩评论