I am creating an app where I have in it a table of content.
I created an XML file to extract the data from it.
In my XML, I want to change in the style of some text however i couldn't do it from the XML code. i tried putting the tags <b>
, <bold>
, <strong>
but they didn't work
Please find below the XML code:
<book>
<item type="Module">
<title>My family and I</title>
</item>
<item type="Unit">
<title>World Friends</title>
</item>
<item type="Unit">
<title>Sport and activities</title>
</item>
<item type="Module">
<title>
<b>School days</b></title>
</item>
<item type="Unit">
<title>My routine</title>
</item>
<item type="Unit">
<title>School life</title>
</item>
</book>
this is my XML. As you see I have 2 types: Module
and Unit
. I want to make the text bold in type module and to indent the text in Unit type.
I also created a class to call the title. I will show u the codes below:
this is my class
public class ContentTable
{
string itemTitle;
public string ItemTitle
{
get { return itemTitle; }
set { itemTitle = value; }
}
}
this is the code to retrieve data.
string XMLPath = Path.Combine(
Package.Current.InstalledLocation.Path, "Assets/tableOfContent.xml");
XDocument loadedData = XDocument.Load(XMLPath);
//retrieving data from xml using LINQ
var data = from query in loadedData.Descendants("item")
select new ContentTable
{
ItemTitle = (string)query.Element("title")
};
//assigning source to GridView Control
AllItemsView.ItemsSource = data;
this is my XAML
<ListBox x:Name="AllItemsView" Width="200" Margin="45,20,5,-604" Height="665" VerticalAlignment="Top" Foreground="Black" Background="White" Grid.RowSpan="2" SelectionChanged="AllItemsView_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10" >
<TextBlock Text="{Binding ItemTitle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
An easy way to address this, were you writing a WPF program, would be to declare a Style
for the TextBlock
in which you use DataTrigger
instances to apply specific formatting to the TextBlock
properties based on the data. Unfortunately, this feature (like a number of other very useful features) isn't in WinRT. As I understand it, the common alternative is to implement IValueConverter
, mapping some input value to the appropriate property value for your formatting. It's not as broadly useful as triggers, but for simple scenarios it works about the same.
Note that whatever you wind up doing, the criteria on which you want to base formatting changes has to flow from the original data to the rendered output. There are a variety of ways to accomplish this, but given your example, it seems to me the simplest is to just add a property to your ContentTable
class:
public class ContentTable
{
public string ItemTitle { get; set; }
public string ItemType { get; set; }
}
To your original ItemTitle
property, I've added ItemType
which will take the type
property value from your XML.
Of course, having added this property, it needs to be populated along with ItemTitle
:
var data = from query in loadedData.Descendants("item")
select new ContentTable
{
ItemTitle = query.Element("title").Value,
ItemType = query.Attribute("type").Value
};
Before we can bind this new property to a relevant TextBlock
property (e.g. FontWeight
or Margin
), we need the converters that will map the specific string
values in the type
attribute to the appropriate property values for TextBlock
:
class ItemTypeToBoldConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
string text = value as string;
if (text != null)
{
return text == "Module" ?
Windows.UI.Text.FontWeights.Bold :
Windows.UI.Text.FontWeights.Normal;
}
return Windows.UI.Xaml.DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
class ItemTypeToMarginConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
string text = value as string;
if (text != null)
{
return text == "Unit" ?
new Windows.UI.Xaml.Thickness(20, 0, 0, 0) :
new Windows.UI.Xaml.Thickness();
}
return Windows.UI.Xaml.DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Having laid all the necessary groundwork, the rest is easy. :)
Your converters can be declared as resources (e.g. so they can be reused for multiple elements or even different DataTemplate
instances):
<Page.Resources>
<local:ItemTypeToBoldConverter x:Key="itemTypeToBoldConverter1"/>
<local:ItemTypeToMarginConverter x:Key="itemTypeToMarginConverter1"/>
</Page.Resources>
Finally, you can reference the converters in the template itself:
<DataTemplate>
<StackPanel Margin="10" >
<TextBlock Text="{Binding ItemTitle}"
FontWeight="{Binding ItemType, Converter={StaticResource itemTypeToBoldConverter1}}"
Margin="{Binding ItemType, Converter={StaticResource itemTypeToMarginConverter1}}"/>
</StackPanel>
</DataTemplate>
The above binds two different properties, FontWeight
and Margin
, to the same data item property, ItemType
. But since they use different converters, they each behave appropriately. When the ItemType
value is Module
, the font weight is set to bold; otherwise, it's set to a normal weight. Similarly, when the ItemType
value is Unit
, the left margin is set to a non-zero value (in this example, I chose 20
); otherwise, it's left set to 0 thickness.
Note that the above translates your XML data directly to XAML UI element property values. In your question, you mention HTML markup, like <b>
, <bold>
, and <strong>
. The above is the simplest approach, and matches best the exact code example and formatting criteria you've provided. But you can't use it to apply HTML formatting. You're stuck with the formatting and layout that's available in XAML. Now, that is in fact a pretty rich formatting environment, but if you want an HTML-based approach, you can do that instead.
There would be lots of options there as well, but IMHO the best way would be to write an XSL stylesheet that transforms your XML to the appropriate HTML document, using the XsltTransform
class to convert (assuming that's available on WinRT…I didn't check). Then you can use the WebView
control (or in WPF, WebBrowser
) to display the HTML.