如何从特定位置而不是相关程序集加载图像?
How to load images from specific location, not from related assembly?
我有 PCL 基于 Xamarin 的解决方案。我需要做的是将图像加载到应用程序项目中的视图中。这些图像在另一个 PCL 项目中。
基本上我有一些 GridView xamarin 视图。此视图应显示类似 'cards' 的内容。所有数据都加载良好,但图像。老实说,我尝试了我能想到的一切——绝对路径、嵌入式资源、相对路径、windows ms-appx/// 前缀。我没有尝试只对我不太有用的流。只有网络资源有效。
我的代码:
[assembly: ExportRenderer(typeof(GridViewRoles), typeof(GridViewRolesRenderer))]
namespace StrangerParty.Windows.Renderers
{
public class GridViewRolesRenderer : ViewRenderer<GridViewRoles, GridView>
{
private GridView gridView;
protected override void OnElementChanged(ElementChangedEventArgs<GridViewRoles> e)
{
base.OnElementChanged(e);
if (this.Control == null)
{
this.gridView = new GridView();
StringBuilder sb = new StringBuilder();
sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">");
sb.Append("<Grid Height=\"100\" Width=\"100\" >"); /*Background =\"#FF2E2E2E\"*/
sb.Append("<Image x:Name=\"ImageRoleImage\" Stretch=\"UniformToFill\" Source=\"sampleForTesting.png\"/>");
sb.Append("</Grid>");
sb.Append("</DataTemplate>");
DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sb.ToString());
this.gridView.ItemTemplate = datatemplate;
SetNativeControl(this.gridView);
}
this.gridView.ItemsSource = Core.Instance.GameHandler.Game.Players;
}
}
}
感谢您的帮助
您可以使用 Assembly.GetManifestResourceStream
从 PCL
加载图像文件。
根据您的要求,您需要使用 Converter
等代码隐藏。
转换器
public object Convert(object value, Type targetType, object parameter, string language)
{
var temp = new BitmapImage();
var assembly = typeof(ImageTest.App).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(value as string);
if (stream != null)
{
using (var memStream = new MemoryStream())
{
stream.CopyTo(memStream);
memStream.Position = 0;
temp.SetSource(memStream.AsRandomAccessStream());
}
}
return temp;
}
下一步是创建 DataTemplate
,要利用 converter
,数据模板不能由 XamlLoader
加载。因此,您可以像下面的代码一样为数据模板创建 <ResourceDictionary>
。
....
xmlns:local="using:ImageTest.UWP"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<DataTemplate x:Key="MyDataTemplate">
<Grid >
<Grid.Resources>
<local:DateToStringConverter x:Key="MyConvert"/>
</Grid.Resources>
<Image Name="MyImage" Source="{Binding imageSource , Mode=OneWay, Converter={StaticResource MyConvert}}" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
MainPage.xaml
<GridView Name="MyGridView" ItemTemplate="{StaticResource MyDataTemplate}"/>
MainPage.xaml.cs
public MainViewModel viewModel { get; set; }
public MainPage()
{
this.InitializeComponent();
viewModel = this.DataContext as MainViewModel;
viewModel.items.Add(new Model() { imageSource = "ImageTest.hello.jpg" });
viewModel.items.Add(new Model() { imageSource= "ImageTest.hello.jpg" });
MyGridView.ItemsSource = viewModel.items;
}
因此您可以使用相同的方式通过加载 <Application.Resources>
来创建您的 DataTemplate
,就像隐藏代码一样。
var ItemTemplate = App.Current.Resources["MyDataTemplate"] as Windows.UI.Xaml.DataTemplate
如果不行。请试试我的 demo.
我有 PCL 基于 Xamarin 的解决方案。我需要做的是将图像加载到应用程序项目中的视图中。这些图像在另一个 PCL 项目中。
基本上我有一些 GridView xamarin 视图。此视图应显示类似 'cards' 的内容。所有数据都加载良好,但图像。老实说,我尝试了我能想到的一切——绝对路径、嵌入式资源、相对路径、windows ms-appx/// 前缀。我没有尝试只对我不太有用的流。只有网络资源有效。
我的代码:
[assembly: ExportRenderer(typeof(GridViewRoles), typeof(GridViewRolesRenderer))]
namespace StrangerParty.Windows.Renderers
{
public class GridViewRolesRenderer : ViewRenderer<GridViewRoles, GridView>
{
private GridView gridView;
protected override void OnElementChanged(ElementChangedEventArgs<GridViewRoles> e)
{
base.OnElementChanged(e);
if (this.Control == null)
{
this.gridView = new GridView();
StringBuilder sb = new StringBuilder();
sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">");
sb.Append("<Grid Height=\"100\" Width=\"100\" >"); /*Background =\"#FF2E2E2E\"*/
sb.Append("<Image x:Name=\"ImageRoleImage\" Stretch=\"UniformToFill\" Source=\"sampleForTesting.png\"/>");
sb.Append("</Grid>");
sb.Append("</DataTemplate>");
DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sb.ToString());
this.gridView.ItemTemplate = datatemplate;
SetNativeControl(this.gridView);
}
this.gridView.ItemsSource = Core.Instance.GameHandler.Game.Players;
}
}
}
感谢您的帮助
您可以使用 Assembly.GetManifestResourceStream
从 PCL
加载图像文件。
根据您的要求,您需要使用 Converter
等代码隐藏。
转换器
public object Convert(object value, Type targetType, object parameter, string language)
{
var temp = new BitmapImage();
var assembly = typeof(ImageTest.App).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(value as string);
if (stream != null)
{
using (var memStream = new MemoryStream())
{
stream.CopyTo(memStream);
memStream.Position = 0;
temp.SetSource(memStream.AsRandomAccessStream());
}
}
return temp;
}
下一步是创建 DataTemplate
,要利用 converter
,数据模板不能由 XamlLoader
加载。因此,您可以像下面的代码一样为数据模板创建 <ResourceDictionary>
。
....
xmlns:local="using:ImageTest.UWP"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<DataTemplate x:Key="MyDataTemplate">
<Grid >
<Grid.Resources>
<local:DateToStringConverter x:Key="MyConvert"/>
</Grid.Resources>
<Image Name="MyImage" Source="{Binding imageSource , Mode=OneWay, Converter={StaticResource MyConvert}}" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
MainPage.xaml
<GridView Name="MyGridView" ItemTemplate="{StaticResource MyDataTemplate}"/>
MainPage.xaml.cs
public MainViewModel viewModel { get; set; }
public MainPage()
{
this.InitializeComponent();
viewModel = this.DataContext as MainViewModel;
viewModel.items.Add(new Model() { imageSource = "ImageTest.hello.jpg" });
viewModel.items.Add(new Model() { imageSource= "ImageTest.hello.jpg" });
MyGridView.ItemsSource = viewModel.items;
}
因此您可以使用相同的方式通过加载 <Application.Resources>
来创建您的 DataTemplate
,就像隐藏代码一样。
var ItemTemplate = App.Current.Resources["MyDataTemplate"] as Windows.UI.Xaml.DataTemplate
如果不行。请试试我的 demo.