如何在 toolbarItems 的 IconImageSource 属性 中支持流图像?
How can I support a stream image in the IconImageSource property of toolbarItems?
我有一个图像可以转换为流并添加到工具栏项的 IconImageSource 属性中。
** 面临的问题 **
将 ToolbarItems 中的 IconImageSource 属性 设置为流 ImageSource。
在 Android 中,它提出了诸如“无法访问已关闭的流,位于 System.IO.MemoryStream.get_Position()”之类的问题。
它不会在 iOS 和 UWP 平台上的 toolbarItems 中显示任何图像。
我在示例中创建了两个 imageSource 属性:OpenToolItem 和 CloseToolItem。
如何在我的应用程序中将流值分配给 OpenToolItem 和 CloseToolItem 属性?
请参考下面的代码。
我的mainpage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<local:TestingControl xmlns:local="clr-namespace:TestStreamControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestStreamControl.MainPage" OpenToolItem="https://aka.ms/campus.jpg"
CloseToolItem="https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg">
</local:TestingControl>
我的mainpage.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TestStreamControl
{
public partial class MainPage : TestingControl
{
public MainPage()
{
InitializeComponent();
Assembly assembly = Assembly.GetExecutingAssembly();
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
var openSource = ImageSource.FromStream(() => openStream);
OpenToolItem = openSource;
Stream closeStream = assembly.GetManifestResourceStream("TestStreamControl.Images.lake_water_natural.jpg");
var closeSource = ImageSource.FromStream(() => closeStream);
CloseToolItem = closeSource;
}
}
}
TestingControl.cs
命名空间 TestStreamControl
{
public partial class TestingControl : ContentPage
{
private ToolbarItem ToolbarItemSource;
public TestingControl()
{
InitializeComponent();
AddToolbarItem();
}
#region Bindable Property
public static readonly BindableProperty OpenToolItemProperty =
BindableProperty.Create(nameof(OpenToolItem), typeof(ImageSource), typeof(TestingControl), default(ImageSource), BindingMode.Default, null, OnPropertyChanged);
public static readonly BindableProperty CloseToolItemProperty =
BindableProperty.Create(nameof(CloseToolItem), typeof(ImageSource), typeof(TestingControl), default(ImageSource), BindingMode.Default, null, OnPropertyChanged);
public static readonly BindableProperty ItemStateProperty =
BindableProperty.Create(nameof(ItemState), typeof(bool), typeof(TestingControl), false, BindingMode.TwoWay, null, OnItemStatePropertyChanged);
#endregion
#region Public Properties
public ImageSource OpenToolItem
{
get { return (ImageSource)GetValue(OpenToolItemProperty); }
set { this.SetValue(OpenToolItemProperty, value); }
}
public ImageSource CloseToolItem
{
get { return (ImageSource)GetValue(CloseToolItemProperty); }
set { this.SetValue(CloseToolItemProperty, value); }
}
public bool ItemState
{
get { return (bool)GetValue(ItemStateProperty); }
set { this.SetValue(ItemStateProperty, value); }
}
#endregion
#region Property changed events
private static void OnPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TestingControl).OnSourcePropertyChanged(oldValue, newValue);
}
private static void OnItemStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TestingControl).OnSourcePropertyChanged(oldValue, newValue);
}
private void OnSourcePropertyChanged(object oldValue, object newValue)
{
UpdateToolbar();
}
#endregion
private void AddToolbarItem()
{
this.ToolbarItemSource = new ToolbarItem
{
Text = "Open",
Priority = int.MaxValue,
Order = ToolbarItemOrder.Primary,
IconImageSource = this.GetToolbarItem()
};
this.ToolbarItems.Add(this.ToolbarItemSource);
this.ToolbarItemSource.Clicked += OnToolbarItemClicked;
}
private void OnToolbarItemClicked(object sender, EventArgs e)
{
if (ItemState)
{
message.Text = "Message sent";
}
else
{
message.Text = "Message Received";
}
this.ItemState = !this.ItemState;
UpdateToolbar();
}
private ImageSource GetToolbarItem()
{
var internalOpenIcon = OpenToolItem ?? (Device.RuntimePlatform == Device.UWP ? "https://aka.ms/campus.jpg" : "https://aka.ms/campus.jpg");
var internalCloseIcon = CloseToolItem ?? (Device.RuntimePlatform == Device.UWP ? "https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg" : "https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg");
return this.ItemState ? internalCloseIcon : internalOpenIcon;
}
private void UpdateToolbar()
{
if (this.ToolbarItemSource != null)
{
if (OpenToolItem != null || CloseToolItem != null)
{
this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
if (OpenToolItem == null && CloseToolItem == null)
{
this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
else
{
// this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
}
}
}
}
TestingControl.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestStreamControl.TestingControl">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!" x:Name="message"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
问题是这些代码行:
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
var openSource = ImageSource.FromStream(() => openStream);
GetManifestResourceStream
在 Imagesource.FromStream()
调用之前。这会打开一个流,一次。 (该流在周围方法 MainPage 构造函数的末尾自动关闭。这稍后会导致错误“无法访问已关闭的流”。)
ImageSource 需要打开流的代码每次需要:
var openSource = ImageSource.FromStream(() =>
{
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
return openStream;
});
GetManifestResourceStream
调用现在在 委托代码中。每次 ToolbarItem 需要流时,该代码都会被调用。
我有一个图像可以转换为流并添加到工具栏项的 IconImageSource 属性中。
** 面临的问题 **
将 ToolbarItems 中的 IconImageSource 属性 设置为流 ImageSource。 在 Android 中,它提出了诸如“无法访问已关闭的流,位于 System.IO.MemoryStream.get_Position()”之类的问题。
它不会在 iOS 和 UWP 平台上的 toolbarItems 中显示任何图像。
我在示例中创建了两个 imageSource 属性:OpenToolItem 和 CloseToolItem。
如何在我的应用程序中将流值分配给 OpenToolItem 和 CloseToolItem 属性?
请参考下面的代码。
我的mainpage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<local:TestingControl xmlns:local="clr-namespace:TestStreamControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestStreamControl.MainPage" OpenToolItem="https://aka.ms/campus.jpg"
CloseToolItem="https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg">
</local:TestingControl>
我的mainpage.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TestStreamControl
{
public partial class MainPage : TestingControl
{
public MainPage()
{
InitializeComponent();
Assembly assembly = Assembly.GetExecutingAssembly();
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
var openSource = ImageSource.FromStream(() => openStream);
OpenToolItem = openSource;
Stream closeStream = assembly.GetManifestResourceStream("TestStreamControl.Images.lake_water_natural.jpg");
var closeSource = ImageSource.FromStream(() => closeStream);
CloseToolItem = closeSource;
}
}
}
TestingControl.cs
命名空间 TestStreamControl {
public partial class TestingControl : ContentPage
{
private ToolbarItem ToolbarItemSource;
public TestingControl()
{
InitializeComponent();
AddToolbarItem();
}
#region Bindable Property
public static readonly BindableProperty OpenToolItemProperty =
BindableProperty.Create(nameof(OpenToolItem), typeof(ImageSource), typeof(TestingControl), default(ImageSource), BindingMode.Default, null, OnPropertyChanged);
public static readonly BindableProperty CloseToolItemProperty =
BindableProperty.Create(nameof(CloseToolItem), typeof(ImageSource), typeof(TestingControl), default(ImageSource), BindingMode.Default, null, OnPropertyChanged);
public static readonly BindableProperty ItemStateProperty =
BindableProperty.Create(nameof(ItemState), typeof(bool), typeof(TestingControl), false, BindingMode.TwoWay, null, OnItemStatePropertyChanged);
#endregion
#region Public Properties
public ImageSource OpenToolItem
{
get { return (ImageSource)GetValue(OpenToolItemProperty); }
set { this.SetValue(OpenToolItemProperty, value); }
}
public ImageSource CloseToolItem
{
get { return (ImageSource)GetValue(CloseToolItemProperty); }
set { this.SetValue(CloseToolItemProperty, value); }
}
public bool ItemState
{
get { return (bool)GetValue(ItemStateProperty); }
set { this.SetValue(ItemStateProperty, value); }
}
#endregion
#region Property changed events
private static void OnPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TestingControl).OnSourcePropertyChanged(oldValue, newValue);
}
private static void OnItemStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as TestingControl).OnSourcePropertyChanged(oldValue, newValue);
}
private void OnSourcePropertyChanged(object oldValue, object newValue)
{
UpdateToolbar();
}
#endregion
private void AddToolbarItem()
{
this.ToolbarItemSource = new ToolbarItem
{
Text = "Open",
Priority = int.MaxValue,
Order = ToolbarItemOrder.Primary,
IconImageSource = this.GetToolbarItem()
};
this.ToolbarItems.Add(this.ToolbarItemSource);
this.ToolbarItemSource.Clicked += OnToolbarItemClicked;
}
private void OnToolbarItemClicked(object sender, EventArgs e)
{
if (ItemState)
{
message.Text = "Message sent";
}
else
{
message.Text = "Message Received";
}
this.ItemState = !this.ItemState;
UpdateToolbar();
}
private ImageSource GetToolbarItem()
{
var internalOpenIcon = OpenToolItem ?? (Device.RuntimePlatform == Device.UWP ? "https://aka.ms/campus.jpg" : "https://aka.ms/campus.jpg");
var internalCloseIcon = CloseToolItem ?? (Device.RuntimePlatform == Device.UWP ? "https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg" : "https://image.shutterstock.com/image-photo/bright-spring-view-cameo-island-600w-1048185397.jpg");
return this.ItemState ? internalCloseIcon : internalOpenIcon;
}
private void UpdateToolbar()
{
if (this.ToolbarItemSource != null)
{
if (OpenToolItem != null || CloseToolItem != null)
{
this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
if (OpenToolItem == null && CloseToolItem == null)
{
this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
else
{
// this.ToolbarItemSource.Text = this.ItemState ? "Close" : "Open";
this.ToolbarItemSource.IconImageSource = this.GetToolbarItem();
}
}
}
}
}
TestingControl.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestStreamControl.TestingControl">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!" x:Name="message"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
问题是这些代码行:
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
var openSource = ImageSource.FromStream(() => openStream);
GetManifestResourceStream
在 Imagesource.FromStream()
调用之前。这会打开一个流,一次。 (该流在周围方法 MainPage 构造函数的末尾自动关闭。这稍后会导致错误“无法访问已关闭的流”。)
ImageSource 需要打开流的代码每次需要:
var openSource = ImageSource.FromStream(() =>
{
Stream openStream = assembly.GetManifestResourceStream("TestStreamControl.Images.Meow2.jpg");
return openStream;
});
GetManifestResourceStream
调用现在在 委托代码中。每次 ToolbarItem 需要流时,该代码都会被调用。