У меня возникли проблемы с получением необходимых результатов из запроса и списка подзапросов из документа XML.
У меня есть следующий XML-документ (вырезанная версия)
<ObjectSet ExportMode="Special" Version="1.5.0.2307" Note="TypesFirst">
<MetaInformation>
<ExportMode Value="Special" />
<RuntimeVersion Value="1.5.0.2307" />
<SourceVersion Value="1.5.0.2307" />
<ServerFullPath Value="/WW_C27" />
</MetaInformation>
<ExportedObjects>
<OI NAME="Source Notifications" TYPE="system.base.Folder">
<OI NAME="Joe Blow" TYPE="notification.EmailNotification">
<PI Name="EmailAddress" Value="[email protected]" />
<PI Name="EmailSubject" Value="TEST ALARM" />
<PI Name="NotificationText" Value="Alarm text: @(AlarmText) Triggered: @(TimeStamp)" />
<PI Name="Status" Value="1" />
<OI NAME="Filter" TYPE="event.filter.Filter" declared="1" hidden="1">
<OI NAME="AlarmState" TYPE="event.filter.expression.Enum" declared="1"></OI>
<OI NAME="Source" TYPE="event.filter.expression.Text" flags="aggregated">
<PI Name="Column" Value="Source" />
<PI Name="DisplayName" Value="Source" />
<OI NAME="Value1" TYPE="event.filter.expression.TextValue" flags="aggregated">
<PI Name="Value" Value="LG Gas Panel Exhaust Fan" />
</OI>
<OI NAME="Value3" TYPE="event.filter.expression.TextValue" flags="aggregated">
<PI Name="Value" Value="LG Dewer Alm" />
</OI>
</OI>
</OI>
</OI>
<OI NAME="John Smith" TYPE="notification.EmailNotification">
<PI Name="EmailAddress" Value="[email protected]" />
<PI Name="EmailSubject" Value="Work ALARM" />
<PI Name="NotificationText" Value="Alarm text: @(AlarmText) Triggered: @(TimeStamp)" />
<PI Name="Status" Value="1" />
<OI NAME="Filter" TYPE="event.filter.Filter" declared="1" hidden="1">
<OI NAME="AlarmState" TYPE="event.filter.expression.Enum" declared="1">
<PI Name="Column" Value="AlarmState" />
<PI Name="DisplayName" Value="Alarm state" />
<PI Name="EnumType" Value="alarm.pt.AlarmState" />
<OI NAME="1" TYPE="event.filter.expression.EnumValue" flags="aggregated">
<PI Name="Value" Value="1" />
</OI>
<OI NAME="0" TYPE="event.filter.expression.EnumValue" flags="aggregated" /></OI>
<OI NAME="Source" TYPE="event.filter.expression.Text" flags="aggregated">
<PI Name="Column" Value="Source" />
<PI Name="DisplayName" Value="Source" />
<OI NAME="Value1" TYPE="event.filter.expression.TextValue" flags="aggregated">
<PI Name="Value" Value="Rm 7 FrzAlm" />
</OI>
<OI NAME="Value2" TYPE="event.filter.expression.TextValue" flags="aggregated">
<PI Name="Value" Value="Dewer Alm" />
</OI>
</OI>
</OI>
</OI>
</OI>
</ExportedObjects>
</ObjectSet>
Таким образом, мне нужно извлечь из вышеуказанного документа XML следующие сведения:
Все вышеперечисленные подробности я могу извлечь и отобразить на своем datagrid.
Тем не менее, для каждого пользователя есть несколько тревожных сообщений, которые мне нужно отображать в datagrid, в качестве дочерних строк под данным, указанным пользователем. На данный момент я не могу этого сделать. Каков наилучший способ достижения требуемого результата?
Из приведенного выше XML-документа следующий типичный элемент, который мне нужно извлечь как дочерний список под каждым пользователем:
<PI Name="Value" Value="Dewer Alm" />
См. Ниже мой код на С#.
List<EmailNotificationClass> NotificationList =
(
from n in XDocument.Load(str_XMLFilePath).Root.Descendants("ExportedObjects").Descendants("OI").Descendants("OI")
where (string)n.Attribute("TYPE") == "notification.EmailNotification"
let attrib_NAME = n.Attribute("NAME")
let attrib_EMAIL = n.XPathSelectElement("./PI[@Name='EmailAddress']").Attribute("Value")
let attrib_SUBJECT = n.XPathSelectElement("./PI[@Name='EmailSubject']").Attribute("Value")
let attrib_NotificationText = n.XPathSelectElement("./PI[@Name='NotificationText']").Attribute("Value")
let attrib_Status = n.XPathSelectElement("./PI[@Name='Status']").Attribute("Value")
let attrib_SourceList = n.XPathSelectElement("//OI/OI[@NAME='Source']/OI/PI[@Name='Value']")
select new EmailNotificationClass
{
EN_NotificationName = attrib_NAME.Value,
EN_EmailAddress = attrib_EMAIL.Value,
EN_EmailSubject = attrib_SUBJECT.Value,
EN_NotificationText = attrib_NotificationText.Value,
EN_Status = attrib_Status.Value,
EN_SourceList = attrib_SourceList.Value //Need to turn this result into a child list
}
).ToList();
//Set DataGrid source
DG_Notifications.ItemsSource = NotificationList;
}
else
{
MessageBox.Show("Please load XML file from the import tab first");
}
}
Любая помощь будет высоко ценится.
ура
Alain
Удалось решить проблему самостоятельно. Для тех, кто, возможно, стек с аналогичной проблемой, проблема была в том, как я определил класс, который содержит данные, которые позже будут отображаться в DataGrid.
Как только я изменил строку "Источники в первом классе" на "Список", мне удалось получить список тревог на человека.
public class EmailNotificationClass
{
//EN = EmailNotification OI in the XML document
public string EN_NotificationName { get; set; }
public string EN_EmailAddress { get; set; }
public string EN_EmailSubject { get; set; }
public string EN_NotificationText { get; set; }
public string EN_Status { get; set; }
public string EN_FilterType { get; set; }
public List<EN_F_SourceClass> Sources { get; set; }
}
public class EN_F_SourceClass
{
public string FilterSource { get; set; }
}
Затем я изменил код позади
List<EmailNotificationClass> NotificationList =
(
from n in XDocument.Load(str_XMLFilePath).Root.Descendants("ExportedObjects").Descendants("OI").Descendants("OI")
where (string)n.Attribute("TYPE") == "notification.EmailNotification"
let attrib_NAME = n.Attribute("NAME")
let attrib_EMAIL = n.XPathSelectElement("./PI[@Name='EmailAddress']").Attribute("Value")
let attrib_SUBJECT = n.XPathSelectElement("./PI[@Name='EmailSubject']").Attribute("Value")
let attrib_NotificationText = n.XPathSelectElement("./PI[@Name='NotificationText']").Attribute("Value")
let attrib_Status = n.XPathSelectElement("./PI[@Name='Status']").Attribute("Value")
select new EmailNotificationClass
{
EN_NotificationName = attrib_NAME.Value,
EN_EmailAddress = attrib_EMAIL.Value,
EN_EmailSubject = attrib_SUBJECT.Value,
EN_NotificationText = attrib_NotificationText.Value,
EN_Status = attrib_Status.Value,
Sources =
(
from source in n.XPathSelectElements("OI/OI[@NAME='Source']/OI/PI[@Name='Value']")
select new EN_F_SourceClass
{
FilterSource = (string)source.Attribute("Value")
}).ToList()
}
).ToList();
//Set DataGrid source
DG_Notifications.ItemsSource = NotificationList;
}
else
{
MessageBox.Show("Please load XML file from the import tab first");
}
Часть xalm была легкой. Просто добавили RowDeetailsTemplate, как следует
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Grid MaxHeight="100">
<ScrollViewer>
<Border BorderThickness="0" Background="#FFB8E8A1" Padding="5">
<DataGrid ItemsSource="{Binding Sources}" IsReadOnly="True" SelectionMode="Single" SelectionUnit="FullRow" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Width="400" Header="Alarms" Binding="{Binding FilterSource}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Border>
</ScrollViewer>
</Grid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
Спасибо за прочтение,
Alain