How can I set the SvgImageSource property of an Image component from the contents of an XmlDocument in a UWP app?
我有一个Windows 10 UWP应用程序,它使用Prism MVVM a,其中我以编程方式在C#中创建了一个在XmlDocument中的SVG XML,我需要在现有的Image组件中显示它。<铅>
在我的XAML中,我有:
1 2 3
| <Image
Source="{x:Bind ViewModel.SvgSource, Mode=OneWay}"
Stretch="Uniform" /> |
在我的ViewModel中,我有:
1 2 3 4 5 6
| private SvgImageSource _svgSource;
public SvgImageSource SvgSource
{
get => _svgSource;
set => _ = SetProperty(ref _svgSource, value);
} |
...然后我通过以下方式在视图模型中设置源:
1 2
| private SVGGenerator generator;
SvgSource = await generator.GetSourceAsync(_generationCancellationTokenSource.Token); |
在我的SVGGenerator类中(除其他方法外):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public async Task <IRandomAccessStream > GetSourceAsync (CancellationToken cancellationToken )
{
return await Task .Run(() =>
{
using (var stringWriter = new StringWriter ())
{
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding .UTF8
};
using (var memoryStream = new MemoryStream ())
{
using (var xmlTextWriter = XmlWriter .Create(memoryStream, settings ))
{
_document .WriteTo(xmlTextWriter );
xmlTextWriter .Flush();
var ramStream = new InMemoryRandomAccessStream ();
memoryStream .CopyTo(ramStream );
ramStream .Seek(0);
return ramStream ;
}
}
}
}, cancellationToken
);
} |
memoryStream.CopyTo(ramStream);行无法编译-CS1503 C#参数1:无法从Windows.Storage.Streams.InMemoryRandomAccessStreama转换。到'System.IO.Stream'-因为MemoryStream不能写入InMemoryRandomAccessStream(或者换句话说,我无法弄清楚该怎么做)。
某些文本,例如如何在Windows 8中将字节数组转换为InMemoryRandomAccessStream或IRandomAccessStream?我已经看到建议使用memoryStream.AsRandomAccessStream(),但我无法弄清楚如何使用.AsRandomAccessStream()扩展方法(这对我不可用,我不知道从哪里获得它,因为可用的代码未显示using语句)。
其他文字,例如https://csharp.hotexamples.com/examples/Windows.Storage.Streams/InMemoryRandomAccessStream/AsStream/php-inmemoryrandomaccessstream-asstream-method-examples.html –建议使用memoryStream.CopyTo(ramStream.AsStream());,但.AsStream()扩展名isna?出于类似原因可用。
此刻我正在转来转去。
我想做的
"全部"是将XmlDocument中的文本直接写到InMemoryRandomAccessStream或将MemoryStream的内容复制到InMemoryRandomAccessStream,但是我无法弄清楚要么做。
有人可以帮我吗?
我是否应该以另一种(更简单的)方式来执行此操作?
- 在写入InMemoryRandomAccessStream之前,将MemoryStream的位置设置为零。写入MemoryStream之后,该位置位于文件的末尾,因此当您读取MemoryStream时,您将不会获得任何数据:memoryStream.postition = 0;
-
感谢您的提示,但我应该更清楚地指出memoryStream.CopyTo(ramStream);行无法编译:CS1503 C#参数1:无法从Windows.Storage.Streams.InMemoryRandomAccessStreama转换。到\\'System.IO.Stream \\'。
-
请参见以下MSDN示例:docs.microsoft.com/en-us/uwp/api/…
-
您是否可以分享有关_document的更多详细信息,我需要制作一个代码示例来重现此信息,还可以为我们共享最小示例以便快速响应。
-
jdweng:感谢您的链接。这似乎使我走得更远,但是现在我遇到了其他我不理解的错误。 (System.ObjectDisposedException:\\'对象已关闭。(来自HRESULT的异常:0x80000013)\\')这是我第一次使用异步处理,SvgImageSource和InMemoryRandomAccessStream,因此我难以确定在哪里问题实际上是由于同时使用它们而产生的。不管怎么说,还是要谢谢你。
-
Nico Zhu:_document只是XmlDocument对象。其中的SVG XML很好,并且可以在TextBlock组件中很好地显示为文本,这就是将文本放入存在问题的SvgImageSource中。抱歉,但是我不愿意公开分享比我已经拥有的更多的代码。如果您可以具体告诉我您的需求,那么我也许可以分享。
-
如果可以共享完整的ViewModel代码,最好制作复制示例
-
视图模型基于我自己的基类(我不想共享),该基类本身基于Prism ViewModelBase,该棱镜基于Prism BindableBase。我想我已经共享了View模型中与此情况相关的所有代码(_generationCancellationTokenSource = new CancellationTokenSource()的定义除外)。上面的GetSourceAsync方法在另一个异步方法内部被调用,以刷新其中的内容。图像组件"",当从标准Prism EventAggregator收到消息时调用。
-
好的,我明白了,我将为此线程编写代码。
-
谢谢你的帮忙。
-
请检查memoryStream参数。它是输出流,但是您将空的memoryStream发送给writer。
-
请尝试将WriteTo修改为Save方法,以确保memoryStream包含内容。
为了测试您的代码,我发现memoryStream参数是输出类型,但是您将空的memoryStream发送给该方法。因此,请尝试将WriteTo修改为Save方法,以确保memoryStream包含内容。我在下面发布了完整的GetSourceAsync,您可以直接使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public async Task <IRandomAccessStream > GetSourceAsync (CancellationToken cancellationToken )
{
return await Task .Run(async () =>
{
using (var stringWriter = new StringWriter ())
{
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding .UTF8
};
using (var memoryStream = new MemoryStream ())
{
using (var xmlTextWriter = XmlWriter .Create(memoryStream, settings ))
{
_document .Save(xmlTextWriter );
xmlTextWriter .Flush();
var ibuffer = memoryStream .GetWindowsRuntimeBuffer();
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream ();
await randomAccessStream .WriteAsync(ibuffer );
randomAccessStream .Seek(0);
return randomAccessStream ;
}
}
}
}, cancellationToken
);
} |
- 非常感谢,但是在直接粘贴代码之后,我现在得到以下错误:在行上:var ibuffer = memoryStream.GetWindowsRuntimeBuffer(); a?我得到一个CS1061'MemoryStream'不包含'GetWindowsRuntimeBuffer'的定义,并且找不到可以接受的扩展方法'GetWindowsRuntimeBuffer'接受类型为'MemoryStream'的第一个参数。 (我无法使用System.Runtime.InteropServices.WindowsRuntime来添加扩展名方法。)请参阅下一条注释...
-
然后在线上等待randomAccessStream.WriteAsync(ibuffer);一个?我得到一个CS0012,在未引用的程序集中定义了类型'IAsyncOperationWithProgress <,>'。您必须添加对程序集'Windows.Foundation.FoundationContract,a?a ??的引用。 (我真的还不知道那是什么意思,但我认为这可能与作为UWP应用程序有关。)
-
GetWindowsRuntimeBuffer名称空间是WindowsRuntimeBufferExtensions,程序集是System.Runtime.WindowsRuntime.dll。我可以为您分享我的代码示例。
-
请检查此样本。
-
我已经通过添加xaml绑定更新了代码示例
-
我将Nuget软件包安装到相关的(.NET 2.0)项目中(服务DLL-我忘了我不在UWP项目中),但是现在我得到了CS0012类型" IBuffer"在程序集中定义没有引用...吗?在var ibuffer = memoryStream.GetWindowsRuntimeBuffer();行上,我可以定义一个变量,例如IBuffer variable = null;就好了,但是代码中的行给出了错误,我不知道为什么一个行得通,而另一个却行不通。 (我已经包含了using System.Runtime.InteropServices.WindowsRuntime;,并且现在似乎可以正常工作。)请参阅下一条评论...
-
我还得到一个CS0012类型'IAsyncOperationWithProgress <,>'在未引用的程序集中定义...在await randomAccessStream.WriteAsync(ibuffer);行上,我不知道这是哪里来的。我必须看到一些非常基本的东西,但是我似乎正在与软件包,引用,名称空间和库一起转圈。您能否进一步提供帮助,或者这两个问题是否需要一个不同的问题? (我通常不会做这种事情,所以我可能会感到困惑。)
-
您运行我的代码示例了吗?对于我的测试,它在我的身边运转良好。
-
抱歉,是的,我应该说我可以毫无问题地运行您的应用程序。不幸的是,我不知道为什么您的应用程序可以正常运行,而我的为什么不运行。我不知道多余的编译器错误来自哪里,因为一切似乎都正确(据我所知)。使用Windows Template Studio创建应用程序会有所不同吗?
-
您将上述代码放在类库中,而不放在uwp项目中,对吗?
-
您能否为我们共享一个具有上述代码的空白模板工作室应用,我将在您的演示基础上进行测试。
-
共享空白的WTS应用程序可能无济于事,因为由于最近对WTS进行的更新,我似乎只能创建新的Windows 10 2004应用程序,但我仍无法在1909年的计算机上进行完全编辑。 WTS告诉我必须对其进行更新,因此我对其进行了更新,然后我无法编辑新的WTS生成的应用程序的XAML页面,因为我的计算机不是最新的。我不知道为什么会发生这种情况,我在等待机器让我更新到最新的Windows版本,以查看是否恢复到正常状态。
-
我决定将所有代码从我的.NET库项目移到我的UWP项目中,以尝试简化问题并简化工作。我猜这可能是在不同名称空间中对同一接口/类的多个定义(或一些类似的混用)的问题,但是我目前没有时间对此进行研究。我很高兴自己的工作。我非常感谢您为此付出的所有时间和精力。你超越了我的期望。非常感谢你。
-
@GarryP,不要打扰,如果答案是有帮助的,请考虑将其标记为谢谢。