【发布时间】:2020-08-31 14:23:20
【问题描述】:
(已编辑:我的实际问题是关于正确设置 ItemsSource,而不是每个 DataGridTextColumn 的绑定!)
问题描述
我正在努力处理一个特定的数据绑定任务,我想将 XML 数据(使用 LINQ,解析为 XElement)绑定到 WPF DataGrid(不是 DataGridView),以便用户可以编辑它。我认为它可能归结为最核心的问题是:
以下 XAML 语句在 C# 代码中的等效项是什么?
<DataGrid x:Name="dtaGrid" ItemsSource="{Binding Path=Elements[track]}"/>
我想,应该是:
dtaGrid.ItemsSource = xml.Elements("track");
不幸的是,C# 语句没有按预期工作:当数据显示在 DataGrid 中时,一旦用户双击 DataGrid 单元格,就会发生 System.InvalidOperationException(“此视图不允许 EditItem”)编辑其内容。使用 XAML 变体,数据既可以显示也可以编辑而不会出错,并且更改会反映在 XML 源中。
由于我在设计时不知道实际 XML 文件的结构,我想在运行时在后面的代码中动态设置 ItemSource(从而能够更改用于绑定的路径) .
工作示例
这是一个工作示例(在 XAML 中完成 ItemsSource 绑定)。抱歉,代码引用很长,我只是认为这可能有助于在上下文中更好地澄清问题。
MainWindow.xaml(注意 DataGrid 的 ItemsSource 是如何在此处显式绑定的 - 我需要能够在运行时在后面的代码中更改此绑定):
<Window x:Class="linq_xml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:linq_xml" mc:Ignorable="d"
Title="MainWindow" Width="1000" Height="700" >
<Grid Margin="8">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="dtaGrid" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
ItemsSource="{Binding Path=Elements[track]}" AutoGenerateColumns="False"/>
<Button x:Name="btn_Save" Grid.Row="1" Grid.Column="0"
Width="100" HorizontalAlignment="Left" Margin="0 8 0 0"
Content="Save XML" Click="Btn_Save_Click"/>
</Grid>
</Window>
MainWindow.xaml.cs(注意未注释的ItemsSource 语句):
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Xml.Linq;
namespace linq_xml
{
public partial class MainWindow : Window
{
private XElement xml;
private readonly string filepath = @"D:\SynologyDrive\Dev\C#\linq-xml\XML-Beispiele\random.xml";
public MainWindow()
{
InitializeComponent();
xml = XElement.Load(filepath); // load xml file
dtaGrid.DataContext = xml; // set LINQ to XML as data context
/* If the following line is used rather than the ItemsSource being bound done in XAML,
* it doesn't work as expected: Once the user tries to edit a cell at runtime,
* a System.InvalidOperationException ("EditItem is not allowed for this view") occurs. */
// dtaGrid.ItemsSource = xml.Elements("track");
List<DataGridTextColumn> columns = new List<DataGridTextColumn>();
columns.Add(new DataGridTextColumn());
columns[^1].Header = "Artist";
columns[^1].Binding = new Binding("Element[artist_name].Value");
columns.Add(new DataGridTextColumn());
columns[^1].Header = "Album";
columns[^1].Binding = new Binding("Element[album_name].Value");
columns.Add(new DataGridTextColumn());
columns[^1].Header = "Duration";
columns[^1].Binding = new Binding("Element[duration].Value");
foreach (DataGridTextColumn c in columns)
{
dtaGrid.Columns.Add(c);
}
}
private void Btn_Save_Click(object sender, RoutedEventArgs e)
{
xml.Save(filepath);
}
}
}
example.xml:
<?xml version="1.0" encoding="utf-8"?>
<data>
<track>
<id>1337</id>
<name>Wonderful World</name>
<duration>128</duration>
<artist_id>13</artist_id>
<artist_name>Trumpet</artist_name>
<album_id>22</album_id>
<album_name>Nice People</album_name>
</track>
<track>
<id>4711</id>
<name>Colorful World</name>
<duration>256</duration>
<artist_id>1</artist_id>
<artist_name>Pink</artist_name>
<album_id>11</album_id>
<album_name>I like the blues</album_name>
</track>
<track>
<id>0815</id>
<name>World</name>
<duration>512</duration>
<artist_id>9</artist_id>
<artist_name>CNN</artist_name>
<album_id>33</album_id>
<album_name>My Finger Is On The Button</album_name>
</track>
</data>
【问题讨论】:
标签: c# xml xaml data-binding datagrid