问题
I am deserializing a XML file into a class and then trying to display some XAML (stored in a property in the class) in a ContentControl.
Here is my XML:
<CallSteps>
<CallStep>
<StepID>20</StepID>
<StepName>Intro</StepName>
<StepXaml>
<![CDATA[<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc="clr-namespace:CallTracker.Library.UserControls.BaseUserControls;assembly=CallTracker.Library">
<uc:LabelValueControl Label="TestLabel" Value="356733" />
</StackPanel>]]>
</StepXaml>
</CallStep>
<CallStep>
<StepID>30</StepID>
<StepName>Intro</StepName>
<StepXaml>
<![CDATA[<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc="clr-namespace:CallTracker.Library.UserControls.BaseUserControls;assembly=CallTracker.Library">
<uc:LabelValueControl Label="TestLabel2" Value="356738124315" />
</StackPanel>]]>
</StepXaml>
</CallStep>
</CallSteps>
This correctly deserializes to a collection of CallStep
objects. Here is what a single CallStep
object looks like:
As part of my code I have a CurrentCallStep
which contains a single CallStep
. I would like to display the XAML contained in StepXaml
within a ContentControl
(or some other container) using something like:
in VM:
/// <summary>
/// Current call step object
/// </summary>
public CallStep CurrentCallStep
{
get { return _CurrentCallStep; }
set
{
_CurrentCallStep = value;
NotifyPropertyChanged(m => m.CurrentCallStep);
}
}
private CallStep _CurrentCallStep;
in View:
<!-- CurrentCallStep contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
Background="LightBlue"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
This however is not converting the XAML to XAML but rather just showing the text like:
How can I get the text in CurrentCallStep.StepXaml
to convert to XAML?
回答1:
You need to use XamlServices.Load()
to deserialize the string from XAML to a FrameworkElement
. The property that is bounnd to should be a FrameworkElement
reference, not a string
reference.
回答2:
I was able to solve this by extracting the CDATA value from each StepXaml
as follows:
/// <summary>
/// Step XAML
/// </summary>
[XmlElement("StepXaml")]
public object StepXaml
{
get { return _StepXaml; }
set
{
if (_StepXaml != value)
{
object _obj;
using (MemoryStream stream = new MemoryStream())
{
// Convert the text into a byte array so that
// it can be loaded into the memory stream.
XmlNode _node = (value as XmlNode[])[0];
if (_node is XmlCDataSection)
{
XmlCDataSection _cDataSection = _node as XmlCDataSection;
byte[] bytes = Encoding.UTF8.GetBytes(_cDataSection.Value);
// Write the XAML bytes into a memory stream.
stream.Write(bytes, 0, bytes.Length);
// Reset the stream's current position back
// to the beginning so that when it is read
// from, the read begins at the correct place.
stream.Position = 0;
// Convert the XAML into a .NET object.
_obj = XamlReader.Load(stream);
_StepXaml = _obj;
NotifyPropertyChanged(m => m.StepXaml);
}
}
}
}
}
private object _StepXaml;
The ContentControl
simply refers to the StepXaml
like:
<!-- CallContent contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
Doing it this way I didn't have to do anything special while deserializing the XML.
来源:https://stackoverflow.com/questions/28987058/wpf-store-xaml-in-property-and-display-in-contentcontrol