WPF:在 属性 中存储 XAML 并在 ContentControl 中显示
WPF: Store XAML in Property and Display in ContentControl
我正在将 XML 文件反序列化为 class,然后尝试显示一些 XAML(存储在 class 中的 属性)在 ContentControl 中。
这是我的 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>
这正确反序列化为 CallStep
个对象的集合。这是单个 CallStep
对象的样子:
作为我代码的一部分,我有一个 CurrentCallStep
,其中包含一个 CallStep
。我想在 ContentControl
(或其他容器)中显示 StepXaml
中包含的 XAML,使用类似:
虚拟机中:
/// <summary>
/// Current call step object
/// </summary>
public CallStep CurrentCallStep
{
get { return _CurrentCallStep; }
set
{
_CurrentCallStep = value;
NotifyPropertyChanged(m => m.CurrentCallStep);
}
}
private CallStep _CurrentCallStep;
在视图中:
<!-- CurrentCallStep contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
Background="LightBlue"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
然而,这并不是将 XAML 转换为 XAML,而只是显示如下文本:
如何将 CurrentCallStep.StepXaml
中的文本转换为 XAML?
您需要使用 XamlServices.Load()
将字符串从 XAML 反序列化为 FrameworkElement
。绑定到的 属性 应该是 FrameworkElement
引用,而不是 string
引用。
我能够通过从每个 StepXaml
中提取 CDATA 值来解决这个问题,如下所示:
/// <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;
ContentControl
只是指 StepXaml
如:
<!-- CallContent contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
这样做我在反序列化 XML.
时不需要做任何特殊的事情
我正在将 XML 文件反序列化为 class,然后尝试显示一些 XAML(存储在 class 中的 属性)在 ContentControl 中。
这是我的 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>
这正确反序列化为 CallStep
个对象的集合。这是单个 CallStep
对象的样子:
作为我代码的一部分,我有一个 CurrentCallStep
,其中包含一个 CallStep
。我想在 ContentControl
(或其他容器)中显示 StepXaml
中包含的 XAML,使用类似:
虚拟机中:
/// <summary>
/// Current call step object
/// </summary>
public CallStep CurrentCallStep
{
get { return _CurrentCallStep; }
set
{
_CurrentCallStep = value;
NotifyPropertyChanged(m => m.CurrentCallStep);
}
}
private CallStep _CurrentCallStep;
在视图中:
<!-- CurrentCallStep contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
Background="LightBlue"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
然而,这并不是将 XAML 转换为 XAML,而只是显示如下文本:
如何将 CurrentCallStep.StepXaml
中的文本转换为 XAML?
您需要使用 XamlServices.Load()
将字符串从 XAML 反序列化为 FrameworkElement
。绑定到的 属性 应该是 FrameworkElement
引用,而不是 string
引用。
我能够通过从每个 StepXaml
中提取 CDATA 值来解决这个问题,如下所示:
/// <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;
ContentControl
只是指 StepXaml
如:
<!-- CallContent contains the XAML for the current call steps to be displayed -->
<ContentControl Content="{Binding CurrentCallStep.StepXaml}"
这样做我在反序列化 XML.
时不需要做任何特殊的事情