XAML、UWP、MVVM、Win2Dの新機能です。Win2DからVirtualBitmapControlを使用し、すぐにイメージをロード
ページビューに非常に大きな画像を表示する必要があります。私はWin2D、特にVirtualBitmapControlとVirtualBitmapExampleを見ています。
これは私がやりたいことに近いですが、私のイメージを選ぶ必要はありません。私はページに移動すると既にその情報を持っています。
コントロールを複製してファイルピッカーを削除しようとしましたが、ページに表示するファイルパスから画像をロードする場所がわかりません。
デバッガをステップ実行すると、ファイルパスのバインディングが設定される前にVirtualBitmapControlが初期化されます。さらに別のレイヤーを追加するには、MVVMも使用しています。そのため、すべてをUserControlとしてカプセル化し、Imageコントロールを使用するのと同じ方法で使用できるようにしました。ここで
は私のXAMLコードです:
public sealed partial class VirtualBitmapControl : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public VirtualBitmapControl()
{
this.InitializeComponent();
if (!DesignMode.DesignModeEnabled)
{
DataContext = this;
}
virtualBitmapOptions = CanvasVirtualBitmapOptions.None;
//virtualBitmapOptions = CanvasVirtualBitmapOptions.CacheOnDemand;
//virtualBitmapOptions = CanvasVirtualBitmapOptions.ReleaseSource;
}
public string LoadedImageInfo { get; private set; }
public bool IsImageLoaded { get { return virtualBitmap != null; } }
//StorageFile PhotoAsStorageFile;
IRandomAccessStream imageStream;
CanvasVirtualBitmap virtualBitmap;
CanvasVirtualBitmapOptions virtualBitmapOptions;
// This is the file we are displaying
public string FilePath
{
get { return (string)GetValue(FilePathProperty); }
set { SetValue(FilePathProperty, value); }
}
// Using a DependencyProperty as the backing store for FilePath.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty FilePathProperty =
DependencyProperty.Register("FilePath", typeof(string), typeof(VirtualBitmapControl),
new PropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged)));
//null);
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as VirtualBitmapControl;
if (d == null)
return;
if (instance.virtualBitmap != null)
{
//instance.virtualBitmap.Invalidate();
//instance.virtualBitmap.InvalidateMeasure();
}
}
private void Control_SizeChanged(object sender, SizeChangedEventArgs e)
{
// TODO: What do I need to do here?
ImageScrollViewer.MaxWidth = double.MaxValue;
ImageScrollViewer.MaxHeight = double.MaxValue;
/* WIN2d sample code
if (smallView)
{
ImageScrollViewer.MaxWidth = ActualWidth/4;
ImageScrollViewer.MaxHeight = ActualHeight/4;
}
else
{
ImageScrollViewer.MaxWidth = double.MaxValue;
ImageScrollViewer.MaxHeight = double.MaxValue;
}*/
}
private void Control_Loading(FrameworkElement sender, object args)
{
System.Diagnostics.Debug.WriteLine("VirtualBitmapControl::Control_Loading");
}
private void Control_Loaded(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("VirtualBitmapControl::Control_Loaded");
}
private void Control_Unloaded(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("VirtualBitmapControl::Control_Unloaded");
if (ImageVirtualControl != null)
{
ImageVirtualControl.RemoveFromVisualTree();
ImageVirtualControl = null;
}
}
private void ImageVirtualControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasVirtualControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
System.Diagnostics.Debug.WriteLine("VirtualBitmapControl::ImageVirtualControl_CreateResources");
if (imageStream != null)
{
args.TrackAsyncAction(LoadVirtualBitmap().AsAsyncAction());
}
}
private void ImageVirtualControl_RegionsInvalidated(Microsoft.Graphics.Canvas.UI.Xaml.CanvasVirtualControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasRegionsInvalidatedEventArgs args)
{
foreach (var region in args.InvalidatedRegions)
{
using (var ds = ImageVirtualControl.CreateDrawingSession(region))
{
if (virtualBitmap != null)
ds.DrawImage(virtualBitmap, region, region);
}
}
}
private async Task LoadVirtualBitmap()
{
if (virtualBitmap != null)
{
virtualBitmap.Dispose();
virtualBitmap = null;
}
LoadedImageInfo = "";
if (imageStream != null)
{
imageStream.Dispose();
imageStream = null;
}
NotifyPropertyChanged();
if (imageStream == null)
{
imageStream = await GetBitmapStreamFromFilePathAsync(this.FilePath);
}
NotifyPropertyChanged();
virtualBitmap = await CanvasVirtualBitmap.LoadAsync(ImageVirtualControl.Device, imageStream, virtualBitmapOptions);
if (ImageVirtualControl == null)
{
// This can happen if the page is unloaded while LoadAsync is running
return;
}
var size = virtualBitmap.Size;
ImageVirtualControl.Width = size.Width;
ImageVirtualControl.Height = size.Height;
ImageVirtualControl.Invalidate();
LoadedImageInfo = string.Format("{0}x{1} image, is {2}CachedOnDemand",
size.Width, size.Height, virtualBitmap.IsCachedOnDemand ? "" : "not ");
NotifyPropertyChanged();
}
private void NotifyPropertyChanged()
{
if (PropertyChanged == null)
return;
foreach (var property in new string[] { "LoadedImageInfo", "IsImageLoaded", "FilePath"})
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
internal async static Task<IRandomAccessStream> GetBitmapStreamFromFilePathAsync(String filePath)
{
IRandomAccessStream imageStream = null;
<trimmed for space>
return imageStream;
}
}
そして、どのように私は私のページのXAMLからのコントロールを使用しています:
<Grid x:Name="rootPhotoGrid" RelativePanel.Below="pageHeader"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True" Background="AntiqueWhite">
<local:VirtualBitmapControl FilePath="{x:Bind ViewModel.LoadedImagePath}"/> </Grid>
を
<UserControl
x:Class="PEERNET.UWPImageViewer.Views.VirtualBitmapControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PEERNET.UWPImageViewer.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Win2Dcanvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
d:DataContext="{d:DesignInstance Type=local:VirtualBitmapControl, IsDesignTimeCreatable=true}"
SizeChanged="Control_SizeChanged"
Unloaded="Control_Unloaded"
Loading="Control_Loading"
Loaded="Control_Loaded">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer HorizontalScrollMode="Enabled"
VerticalScrollMode="Enabled"
ZoomMode="Disabled"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
x:Name="ImageScrollViewer">
<Grid>
<Win2Dcanvas:CanvasVirtualControl
x:Name="ImageVirtualControl"
CreateResources="ImageVirtualControl_CreateResources"
RegionsInvalidated="ImageVirtualControl_RegionsInvalidated"/>
</Grid>
</ScrollViewer>
</Grid>
</UserControl>
そしてここでは、コードビハインドであります
誰かが正しい方向に私を向けることができ、あるいは私が間違ってやっていることを教えてくれたり、私が逃していることを教えてもらえれば、 preciated。シェリ
だけ今まで私は、そのページに行き、非常に最初の時間後に呼び出されます。私は別のページ(MVVMとViewModel Locaterを使用して)からこのページを前後にナビゲートしています。新しいイメージ(別のページから選択し、ユーザーコントロールのFilePathプロパティとして設定)が必要です。ページ。私はまた、Control_UnloadedでImageVirtualControlのアンロードをコメントアウトするか、ページに戻ったときにnull参照を取得していました。 – SheriSteeves
一般に、私は、ページを再訪したときにWin2Dコントロールを再利用するためにキャッシュすることを勧めません。各Win2Dコントロールは、ページが見えなくなったときに本当に解放したいGPUリソースをかなり消費します。 ページキャッシュを無効にするには、NavigationCacheModeをDisabledに設定します(詳細はhttp://mikaelkoskinen.net/post/winrt-navigation-cache-or-why-going-back-to-previous-page-creates-a-新しいインスタンスのインスタンス) 代替(より複雑な)アプローチ:https://blogs.msdn.microsoft.com/win2d/2015/01/29/loading-win2d-resources-from-outside-the -createresources-event / –