Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6552857
  • 博文数量: 915
  • 博客积分: 17977
  • 博客等级: 上将
  • 技术积分: 8846
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-26 09:59
个人简介

一个好老好老的老程序员了。

文章分类

全部博文(915)

文章存档

2022年(9)

2021年(13)

2020年(10)

2019年(40)

2018年(88)

2017年(130)

2015年(5)

2014年(12)

2013年(41)

2012年(36)

2011年(272)

2010年(1)

2009年(53)

2008年(65)

2007年(47)

2006年(81)

2005年(12)

分类: Android平台

2019-11-13 09:12:21

一个Color ViewModel
Color始终提供了探索图形用户界面功能的好方法,因此您可能不会惊讶于Xamarin.FormsBook.Toolkit库包含一个名为ColorViewModel的类。
ColorViewModel类公开Color属性,但也显示Red,Green,Blue,Alpha,Hue,Saturation和Luminosity属性,所有这些属性都是可单独设置的。这不是Xamarin.Form Color结构提供的功能。从Color构造函数或Color中的其中一个方法创建Color值时,以Add,From,Multiply或With开头,它是不可变的。
ColorViewModel类因其Color属性和所有组件属性的相互关系而变得复杂。例如,假设已设置Color属性。该类应该不仅为Color而且还为任何也发生变化的组件(如Red或Hue)触发PropertyChanged处理程序。同样,如果Red属性发生变化,那么该类应该为Red和Color以及可能的Hue,Saturation和Luminosity触发PropertyChanged事件。
ColorViewModel类通过仅为Color属性存储支持字段来解决此问题。通过调用Color.FromRgba或Color.FromHsla使用传入值,各个组件的所有Set访问器都会创建一个新Color。此新Color值设置为Color属性而不是Color字段,这意味着新Color值将在Color属性的Set访问器中进行处理:

点击(此处)折叠或打开

  1. public class ColorViewModel : INotifyPropertyChanged
  2. {
  3.     Color color;
  4.     public event PropertyChangedEventHandler PropertyChanged;
  5.     public double Red
  6.     {
  7.         set
  8.         {
  9.             if (Round(color.R) != value)
  10.                 Color = Color.FromRgba(value, color.G, color.B, color.A);
  11.         }
  12.         get
  13.         {
  14.             return Round(color.R);
  15.         }
  16.     }
  17.     public double Green
  18.     {
  19.         set
  20.         {
  21.             if (Round(color.G) != value)
  22.                 Color = Color.FromRgba(color.R, value, color.B, color.A);
  23.         }
  24.  
  25.         get
  26.         {
  27.             return Round(color.G);
  28.         }
  29.     }
  30.     public double Blue
  31.     {
  32.         set
  33.         {
  34.             if (Round(color.B) != value)
  35.                 Color = Color.FromRgba(color.R, color.G, value, color.A);
  36.         }
  37.         get
  38.         {
  39.             return Round(color.B);
  40.         }
  41.     }
  42.     public double Alpha
  43.     {
  44.         set
  45.         {
  46.             if (Round(color.A) != value)
  47.                 Color = Color.FromRgba(color.R, color.G, color.B, value);
  48.         }
  49.         get
  50.         {
  51.             return Round(color.A);
  52.         }
  53.     }
  54.     public double Hue
  55.     {
  56.         set
  57.         {
  58.             if (Round(color.Hue) != value)
  59.                 Color = Color.FromHsla(value, color.Saturation, color.Luminosity, color.A);
  60.         }
  61.         get
  62.         {
  63.             return Round(color.Hue);
  64.         }
  65.     }
  66.     public double Saturation
  67.     {
  68.         set
  69.         {
  70.             if (Round(color.Saturation) != value)
  71.                 Color = Color.FromHsla(color.Hue, value, color.Luminosity, color.A);
  72.         }
  73.         get
  74.         {
  75.             return Round(color.Saturation);
  76.         }
  77.     }
  78.     public double Luminosity
  79.     {
  80.         set
  81.         {
  82.             if (Round(color.Luminosity) != value)
  83.                 Color = Color.FromHsla(color.Hue, color.Saturation, value, color.A);
  84.         }
  85.         get
  86.         {
  87.             return Round(color.Luminosity);
  88.         }
  89.     }
  90.     public Color Color
  91.     {
  92.         set
  93.         {
  94.             Color oldColor = color;
  95.             if (color != value)
  96.             {
  97.                 color = value;
  98.                 OnPropertyChanged("Color");
  99.             }
  100.             if (color.R != oldColor.R)
  101.                 OnPropertyChanged("Red");
  102.             if (color.G != oldColor.G)
  103.                 OnPropertyChanged("Green");
  104.             if (color.B != oldColor.B)
  105.                 OnPropertyChanged("Blue");
  106.             if (color.A != oldColor.A)
  107.                 OnPropertyChanged("Alpha");
  108.             if (color.Hue != oldColor.Hue)
  109.                 OnPropertyChanged("Hue");
  110.             if (color.Saturation != oldColor.Saturation)
  111.                 OnPropertyChanged("Saturation");
  112.             if (color.Luminosity != oldColor.Luminosity)
  113.                 OnPropertyChanged("Luminosity");
  114.         }
  115.         get
  116.         {
  117.             return color;
  118.         }
  119.     }
  120.     protected void OnPropertyChanged(string propertyName)
  121.     {
  122.         PropertyChangedEventHandler handler = PropertyChanged;
  123.         if (handler != null)
  124.         {
  125.             handler(this, new PropertyChangedEventArgs(propertyName));
  126.         }
  127.     }
  128.     double Round(double value)
  129.     {
  130.         return Device.OnPlatform(value, Math.Round(value, 3), value);
  131.     }
  132. }
Color属性的Set访问器负责根据属性的更改来触发所有PropertyChanged事件。


请注意类底部的设备相关Round方法及其在set中的使用以及前七个属性的get访问器。 当第23章“触发器和行为”中的MultiColorSliders示例显示出问题时,会添加此项。 Android似乎在内部舍入颜色组件,导致传递给它的属性之间的不一致Color.FromRgba和Color.FromHsla方法以及由此产生的Color值的属性,从而导致无限集和get循环。
HslSliders程序在Grid.BindingContext标记之间实例化ColorViewModel,使其成为Grid中所有Slider和Label元素的BindingContext:

点击(此处)折叠或打开

  1. <ContentPage xmlns=""
  2.              xmlns:x=""
  3.              xmlns:toolkit=
  4.                  "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
  5.              x:Class="HslSliders.HslSlidersPage"
  6.              SizeChanged="OnPageSizeChanged">
  7.  
  8.     <ContentPage.Padding>
  9.         <OnPlatform x:TypeArguments="Thickness"
  10.                     iOS="0, 20, 0, 0" />
  11.     </ContentPage.Padding>
  12.     <Grid x:Name="mainGrid">
  13.         <Grid.BindingContext>
  14.             <toolkit:ColorViewModel Color="Gray" />
  15.         </Grid.BindingContext>
  16.         <Grid.Resources>
  17.             <ResourceDictionary>
  18.                 <Style TargetType="Label">
  19.                     <Setter Property="FontSize" Value="Large" />
  20.                     <Setter Property="HorizontalTextAlignment" Value="Center" />
  21.                 </Style>
  22.             </ResourceDictionary>
  23.         </Grid.Resources>
  24.         <!-- Initialized for portrait mode. -->
  25.         <Grid.RowDefinitions>
  26.             <RowDefinition Height="*" />
  27.             <RowDefinition Height="Auto" />
  28.         </Grid.RowDefinitions>
  29.         <Grid.ColumnDefinitions>
  30.             <ColumnDefinition Width="*" />
  31.             <ColumnDefinition Width="0" />
  32.         </Grid.ColumnDefinitions>
  33.         <BoxView Color="{Binding Color}"
  34.                  Grid.Row="0" Grid.Column="0" />
  35.         <StackLayout x:Name="controlPanelStack"
  36.                      Grid.Row="1" Grid.Column="0"
  37.                      Padding="10, 5">
  38.  
  39.             <StackLayout VerticalOptions="CenterAndExpand">
  40.                 <Slider Value="{Binding Hue}" />
  41.                 <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
  42.             </StackLayout>
  43.             <StackLayout VerticalOptions="CenterAndExpand">
  44.                 <Slider Value="{Binding Saturation}" />
  45.                 <Label Text="{Binding Saturation,StringFormat='Saturation = {0:F2}'}" />
  46.             </StackLayout>
  47.             <StackLayout VerticalOptions="CenterAndExpand">
  48.                 <Slider Value="{Binding Luminosity}" />
  49.                 <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
  50.             </StackLayout>
  51.         </StackLayout>
  52.     </Grid>
  53. </ContentPage>
请注意,实例化ColorViewModel时,ColorViewModel的Color属性已初始化。 然后滑块的双向绑定将获取Hue,Saturation和Luminosity属性的结果值。
如果您想要实现红色,绿色和蓝色的十六进制值的显示,则可以使用与前一章中的GridRgbSliders程序相关的DoubleToIntConverter类。
HslSliders程序实现了与纵向和横向模式之间切换相同的技术,如GridRgbSliders程序。 代码隐藏文件处理此开关的机制:
这个代码隐藏文件不像只调用InitializeComponent的文件那么漂亮,但即使在MVVM的上下文中,纵向和横向模式之间的切换也是代码隐藏文件的合法使用,因为它仅用于 用户界面而不是底层业务逻辑。

这是HslSliders计划的实际应用:
2018_10_12_095158

阅读(4291) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~