【问题标题】:Offline Image Cache in WPFWPF 中的脱机图像缓存
【发布时间】:2019-01-13 14:39:25
【问题描述】:

我有一个 WPF 应用程序,它在有 Internet 连接时从 URL 加载图像,并且当没有活动的 Internet 连接时应该从缓存中加载这些图像

我的问题是 - 在没有任何有效互联网连接的情况下,图像不会被缓存以显示在后续应用启动中。

我已经搜索了几个小时并尝试了 CreateOptionsCacheOption 的几乎所有可能组合,但结果相同。

XAML 代码是这样的:

              <Image
                   Width="{Binding MY_TILE_W}" MaxWidth="380" 
                   Height="{Binding MY_TILE_H}" MaxHeight="240" 
                   Stretch="UniformToFill">

                    <Image.CacheMode>
                        <BitmapCache  EnableClearType="False"
                              RenderAtScale="1"
                              SnapsToDevicePixels="False" />
                    </Image.CacheMode>

                    <Image.Source>
                        <BitmapImage UriSource="{Binding ImageUrl}" 
                             CreateOptions="IgnoreImageCache"
                             CacheOption="OnLoad"/>
                    </Image.Source>

                </Image>

没有更多的C# 代码,当然除了Binding 代码。

是否有可能实现我正在尝试的目标?如果是,请问怎么做?

编辑: 我的问题与this SO post 并不完全相同,正如@Wilson 的评论中所指出的那样 - 因为在我的用例中每次下载图像都不同,但the accepted answer's mentioned CachedImage library 已经部分解决了这个问题。

我用the library's这个ui元素替换了Image块:

<cachedImage:Image Grid.Row="0" Grid.ColumnSpan="2"
        Width="{Binding MY_TILE_W}" MaxWidth="380" 
        Height="{Binding MY_TILE_H}" MaxHeight="240" 
        Stretch="UniformToFill"
        ImageUrl="{Binding ImageUrl}"/>

然后从 VS 2017 直接构建在离线图像缓存中运行良好,但生成的安装文件(使用 Inno-setup)崩溃并显示以下日志:

Set property 'System.Windows.Controls.ItemsControl.ItemTemplate' threw an exception.
Stack Trace:    at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at MyApp.MyWindow.InitializeComponent() in E:\w_Development\DotNet\MyApp\MyWindow.xaml:line 1
   at MyApp.MyWindow..ctor(Window window) in E:\w_Development\DotNet\MyApp\MyWindow.xaml.cs:line 54
   at MyApp.MainWindow.<NavigateWithDelay>d__3.MoveNext() in E:\w_Development\DotNet\MyApp\MainWindow.xaml.cs:line 35
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at MyApp.App.Main()

我已发布an issue regarding this crash in library's issue-board

【问题讨论】:

标签: c# wpf image caching bitmap


【解决方案1】:

使用CachedImage library 符合标准,如this SO answer 中所述。

我用库的这个 ui 元素替换了 Image 块:

<cachedImage:Image Grid.Row="0" Grid.ColumnSpan="2"
        Width="{Binding MY_TILE_W}" MaxWidth="380" 
        Height="{Binding MY_TILE_H}" MaxHeight="240" 
        Stretch="UniformToFill"
        ImageUrl="{Binding ImageUrl}"/>

然后在使用 InnoSetup 脚本生成安装文件后出现异常,因为没有在我的 InnoSetup 脚本中添加DLL reference。现在一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2012-05-31
    相关资源
    最近更新 更多