是否可以让 XamlWriter 保存 StaticResource?
Is it possible to get XamlWriter to save a StaticResource?
我的问题显示在以下程序中,其中 GeometryModel3D 的 Material 是从 XAML 中的 StaticResource 设置的。
是否可以让 XamlWriter 保存实际的 StaticResources 而不是解析的引用(它现在这样做)?如果可以,我需要做什么?
using System;
using System.IO;
using System.Text;
using System.Windows.Controls;
using System.Windows.Markup;
namespace MaterialTest
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string xaml = "";
xaml += "<Viewport3D xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>";
xaml += " <Viewport3D.Resources>";
xaml += " <DiffuseMaterial x:Key='Steel' />";
xaml += " </Viewport3D.Resources>";
xaml += " <ModelVisual3D>";
xaml += " <ModelVisual3D.Content>";
xaml += " <GeometryModel3D Material='{StaticResource Steel}'>";
xaml += " <GeometryModel3D.Geometry>";
xaml += " <MeshGeometry3D Positions='-0.5,-0.5,0 0.5,-0.5,0 0.5,0.5,0 -0.5,0.5,0' TriangleIndices='0 1 2 0 2 3' />";
xaml += " </GeometryModel3D.Geometry>";
xaml += " </GeometryModel3D>";
xaml += " </ModelVisual3D.Content>";
xaml += " </ModelVisual3D>";
xaml += "</Viewport3D>";
MemoryStream buffer = new MemoryStream(Encoding.UTF8.GetBytes(xaml));
Viewport3D viewport = XamlReader.Load(buffer) as Viewport3D;
string xaml_out = XamlWriter.Save(viewport);
}
}
}
Is it possible to get the XamlWriter to save out the actual StaticResources instead of the resolved references (which it does now)?
不,恐怕不是。这是 MSDN 上记录的 XamlWriter.Save
的已知限制:https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/serialization-limitations-of-xamlwriter-save
Common references to objects made by various markup extension formats, such as StaticResource
or Binding
, will be dereferenced by the serialization process. These were already dereferenced at the time that in-memory objects were created by the application runtime, and the Save logic does not revisit the original XAML to restore such references to the serialized output.
我之前遇到过与绑定相同的问题,我在这个 link 中找到了序列化绑定的解决方案:
Binding Serialization
并且,基于这个解决方案,我发现了如何“过滤”样式序列化。
定义序列化时的样式 return,StyleConverterClass:
class StyleConverter : System.Windows.ExpressionConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
return true;
else return false;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
{
Style style = value as Style;
if (style == null)
throw new Exception();
foreach (var dictionarys in ((MetroWindow)Application.Current.MainWindow).Resources.MergedDictionaries)
{
foreach (DictionaryEntry entry in dictionarys)
{
if (entry.Value is Style && (entry.Value as Style) == style)
{
return new StaticResourceExtension(entry.Key);
}
}
}
return style;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
需要注意的重要一点是 StaticResourceExtension class.
的使用
然后,重新注册:
EditorHelper.Register<Style, ExpressionConverter.StyleConverter>();
瞧,当 Style 被序列化时,它将 return StaticResourceExtension 的实例而不是 Style 实例,因此,避免将整个 Style 描述写入导出的 xaml .导出组件的样式将如下所示:
<cuc:ComboBoxWrapper IsDropDownOpen="False" Style="{av:StaticResource
ResourceKey=MahApps.Styles.ComboBox.Virtualized}" av:Grid.Column="0"
av:Grid.Row="1" />
我的问题显示在以下程序中,其中 GeometryModel3D 的 Material 是从 XAML 中的 StaticResource 设置的。
是否可以让 XamlWriter 保存实际的 StaticResources 而不是解析的引用(它现在这样做)?如果可以,我需要做什么?
using System;
using System.IO;
using System.Text;
using System.Windows.Controls;
using System.Windows.Markup;
namespace MaterialTest
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string xaml = "";
xaml += "<Viewport3D xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>";
xaml += " <Viewport3D.Resources>";
xaml += " <DiffuseMaterial x:Key='Steel' />";
xaml += " </Viewport3D.Resources>";
xaml += " <ModelVisual3D>";
xaml += " <ModelVisual3D.Content>";
xaml += " <GeometryModel3D Material='{StaticResource Steel}'>";
xaml += " <GeometryModel3D.Geometry>";
xaml += " <MeshGeometry3D Positions='-0.5,-0.5,0 0.5,-0.5,0 0.5,0.5,0 -0.5,0.5,0' TriangleIndices='0 1 2 0 2 3' />";
xaml += " </GeometryModel3D.Geometry>";
xaml += " </GeometryModel3D>";
xaml += " </ModelVisual3D.Content>";
xaml += " </ModelVisual3D>";
xaml += "</Viewport3D>";
MemoryStream buffer = new MemoryStream(Encoding.UTF8.GetBytes(xaml));
Viewport3D viewport = XamlReader.Load(buffer) as Viewport3D;
string xaml_out = XamlWriter.Save(viewport);
}
}
}
Is it possible to get the XamlWriter to save out the actual StaticResources instead of the resolved references (which it does now)?
不,恐怕不是。这是 MSDN 上记录的 XamlWriter.Save
的已知限制:https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/serialization-limitations-of-xamlwriter-save
Common references to objects made by various markup extension formats, such as
StaticResource
orBinding
, will be dereferenced by the serialization process. These were already dereferenced at the time that in-memory objects were created by the application runtime, and the Save logic does not revisit the original XAML to restore such references to the serialized output.
我之前遇到过与绑定相同的问题,我在这个 link 中找到了序列化绑定的解决方案: Binding Serialization
并且,基于这个解决方案,我发现了如何“过滤”样式序列化。
定义序列化时的样式 return,StyleConverterClass:
class StyleConverter : System.Windows.ExpressionConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
return true;
else return false;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
{
Style style = value as Style;
if (style == null)
throw new Exception();
foreach (var dictionarys in ((MetroWindow)Application.Current.MainWindow).Resources.MergedDictionaries)
{
foreach (DictionaryEntry entry in dictionarys)
{
if (entry.Value is Style && (entry.Value as Style) == style)
{
return new StaticResourceExtension(entry.Key);
}
}
}
return style;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
需要注意的重要一点是 StaticResourceExtension class.
的使用然后,重新注册:
EditorHelper.Register<Style, ExpressionConverter.StyleConverter>();
瞧,当 Style 被序列化时,它将 return StaticResourceExtension 的实例而不是 Style 实例,因此,避免将整个 Style 描述写入导出的 xaml .导出组件的样式将如下所示:
<cuc:ComboBoxWrapper IsDropDownOpen="False" Style="{av:StaticResource ResourceKey=MahApps.Styles.ComboBox.Virtualized}" av:Grid.Column="0" av:Grid.Row="1" />