当前位置:首页 > Windows程序 > 正文

Windows 10 开发日记(五)

2021-05-26 Windows程序


前文再续,上一章提出了问题,本章提出了三种解决方案:

解决方案一:手动进行异步转换,核心思想:将binding做的事情放入CodeBehind

FilterItemControl.XAML:

<Grid> <Image x:Name="FilterImage" Stretch="UniformToFill"/> <Grid VerticalAlignment="Bottom"> <TextBlock x:Name="FilterName" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/> </Grid> <Border x:Name="border" BorderBrush="White" BorderThickness="1" d:LayoutOverrides="LeftPosition, RightPosition, TopPosition, BottomPosition" Margin="1" Visibility="Collapsed"/> </Grid>

  

FilterItemControl.cs

/// <summary> /// 设置数据源 /// </summary> /// <param></param> public async void SetSource(Filter filter) { if (filter != null) { _filter = filter; // 使用WriteableBitmap有一个不好的点:必须要知道图片的大小 WriteableBitmap result = new WriteableBitmap(768, 1280); var wbData = await MyFilterSDK.ProcessFilterAsync(filter); if(wbData != null) { using (var bmpStream = result.PixelBuffer.AsStream()) { bmpStream.Seek(0, SeekOrigin.Begin); bmpStream.Write(wbData, 0, (int)bmpStream.Length); } FilterImage.Source = result; } FilterName.Text = filter.FilterName; } }

为其设置数据源, FilterItemsControl.cs

/// <summary> /// 数据源发生变化 /// </summary> /// <param>滤镜列表</param> private void OnItemsSourceChanged(List<Filter> filters) { if(filters != null) { Container.Children.Clear(); foreach(var filter in filters) { FilterItemControl itemcontrol = new FilterItemControl(); itemcontrol.Width = ITEMWIDTH; itemcontrol.Height = ITEMHEIGHT; // 将binding中做的事情放到代码中! itemcontrol.SetSource(filter);
itemcontrol.ItemSelected += Itemcontrol_ItemSelected; itemcontrol.ItemDoubleClicked += Itemcontrol_ItemDoubleClicked; Container.Children.Add(itemcontrol); } } }

  优点:方便简单

缺点:XAML必须写死,没有扩展性,如果同样的数据变换一种显示方式,需要重写一个控件。

解决方案二:使用异步属性,核心思想,使用Binding和异步加载

FilterItemControl.xaml

<Grid> <Image x:Name="FilterImage" Stretch="UniformToFill" Source="{Binding WBAsyncProperty.AsyncValue, Converter={StaticResource imagConverter}}"/> <Grid VerticalAlignment="Bottom"> <TextBlock x:Name="FilterName" TextWrapping="Wrap" Text="{Binding FilterName}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/> </Grid> <Border x:Name="border" BorderBrush="White" BorderThickness="1" d:LayoutOverrides="LeftPosition, RightPosition, TopPosition, BottomPosition" Margin="1" Visibility="Collapsed"/> </Grid>

FilterItemControl.cs不需要额外的东西,但是Model层的数据源需要增加一个异步属性用于被View层绑定

Filter.cs

private AsyncProperty<byte[]> _wbAsyncProperty; // 异步属性 public AsyncProperty<byte[]> WBAsyncProperty { get { return _wbAsyncProperty; } set { SetProperty(ref _wbAsyncProperty, value); } }
     // 初始化 public Filter() { WBAsyncProperty = new AsyncProperty<byte[]>(async () => { var result = await MyFilterSDK.ProcessFilterAsync(this); return result; }); }

  

由于返回值是byte[]类型,所以我们在binding时,必须要进行一次转换,将其转换为WriteableBitmap:BytesToImageConverter.cs

public class BytesToImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { // 使用WriteableBitmap有一个不好的点:必须要知道图片的大小 WriteableBitmap result = new WriteableBitmap(768, 1280); var filterData = value as byte[]; if (filterData != null) { #region WriteableBitmap方案 using (var bmpStream = result.PixelBuffer.AsStream()) { bmpStream.Seek(0, SeekOrigin.Begin); bmpStream.Write(filterData, 0, (int)bmpStream.Length); return result; } #endregion } else return null; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }

  关于如何实现AsyncProperty和其工作原理在这里不做深究,在这里总结一下这个方案的优缺点:

优点:使用Binding,UI上不会卡顿,图片获取完之后会显示在UI上

缺点: 1. 控件重用性不高

2. SDK必须与UI无关,这也是为什么返回byte[],而不是直接返回WrieableBitmap的原因,与AsyncProperty的实现技术有关

3. 因为原因2,必须实现转换器

解决方案三:使用DataTemplate,核心思想:将DataTemplate转换放到CodeBehind

FilterItemControl.XAML需要改变,这里只需要一个ContentPresenter接收内容

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/71361.html