4

是否可以通过 xaml 将 Isolates 存储中存在的图像绑定到图像控件。我发现了一些实现,比如通过属性获取图像并将其绑定到 xaml 控件中。但这不是我正在寻找的实现。我的问题是,编写一个附加属性和辅助方法来从独立存储中获取内容。我在 Windows phone 7 中使用的 LowProfileImage 类中找到了类似的实现。但我认为它现在已被弃用。如果有人尝试过类似的实现,请帮助我实现相同的目标。此外,如果实施有任何性能消耗,请也提及该信息。

4

2 回答 2

10

是的,可以在应用程序 UI 中使用来自隔离存储的图像。它需要将文件中的图像加载到 中BitmapImage,然后将ImageSource您的控件绑定到该BitmapImage. 我正在使用以下方法:

首先,有一种异步加载图像的方法:

private Task<Stream> LoadImageAsync(string filename)
    {
        return Task.Factory.StartNew<Stream>(() =>
        {
            if (filename == null)
            {
                throw new ArgumentException("one of parameters is null");
            }

            Stream stream = null;

            using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isoStore.FileExists(filename))
                {
                    stream = isoStore.OpenFile(filename, System.IO.FileMode.Open, FileAccess.Read);                               
                }
            }
            return stream;
        });
    }

然后可以这样使用:

public async Task<BitmapSource> FetchImage()
    {
        BitmapImage image = null;
        using (var imageStream = await LoadImageAsync(doc.ImagePath))
        {
            if (imageStream != null)
            {
                image = new BitmapImage();
                image.SetSource(imageStream);
            }
        }
        return image;
    }

最后,您只需将方法的返回值分配给FetchImage()您的视图模型的某些属性,UI 元素绑定到这些属性。当然,您的视图模型应该正确实现INotifyPropertyChanged接口以使这种方法可靠地工作。


如果你想使用附加属性的方法,你可以这样做:

public class IsoStoreImageSource : DependencyObject
{
    public static void SetIsoStoreFileName(UIElement element, string value)
    {
        element.SetValue(IsoStoreFileNameProperty, value);
    }
    public static string GetIsoStoreFileName(UIElement element)
    {
        return (string)element.GetValue(IsoStoreFileNameProperty);
    }

    // Using a DependencyProperty as the backing store for IsoStoreFileName.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsoStoreFileNameProperty =
        DependencyProperty.RegisterAttached("IsoStoreFileName", typeof(string), typeof(IsoStoreImageSource), new PropertyMetadata("", Changed));

    private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Image img = d as Image;

        if (img != null)
        {
            var path = e.NewValue as string;
            SynchronizationContext uiThread = SynchronizationContext.Current;

            Task.Factory.StartNew(() =>
            {
                using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (isoStore.FileExists(path))
                    {
                        var stream = isoStore.OpenFile(path, System.IO.FileMode.Open, FileAccess.Read);
                        uiThread.Post(_ =>
                        {
                            var _img = new BitmapImage();
                            _img.SetSource(stream);
                            img.Source = _img;
                        }, null);
                    }
                }
            });               
        }
    }
}

然后在 XAML 中:

<Image local:IsoStoreImageSource.IsoStoreFileName="{Binding Path}" />

这种方法的一些限制:

  • 它仅适用于Image控制,尽管您可以将其更改为您想要的任何类型。它只是不是很通用。
  • 性能方面,每次更改图像源时,它将使用线程池中的一个线程。这是目前从 Windows Phone 8 上的隔离存储中进行异步读取的唯一方法。而且您绝对不想同步执行此操作。

但它有一个重要的优势:

  • 有用!:)
于 2013-04-19T11:24:05.543 回答
1

我喜欢上面的方法,但如果你有兴趣,还有一种更简单、更老套的方法。

您可以进入您的 xaml 并将图像源绑定到字符串属性,然后将文件路径动态地放入属性中。

<!-- XAML CODE -->
 <Image Source="{Binding imagePath}"/>


//Behind property
public String imagePath { get; set; }

将您的路径加载到图像路径中,然后将图像源绑定到图像路径字符串。您可能必须执行 INotifyPropertyChanged 但此方法应与正确绑定一起使用。

于 2013-04-19T15:18:45.140 回答