■ x:DataType 속성에서 컴파일된 바인딩과 클래식 바인딩을 함께 사용하는 방법을 보여준다.
▶ NamedColor.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
using System.Reflection; using System.Text; namespace TestProject; /// <summary> /// 이름있는 색상 /// </summary> public class NamedColor : IEquatable<NamedColor>, IComparable<NamedColor> { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 이름있는 색상 리스트 - NamedColorList /// <summary> /// 이름있는 색상 리스트 /// </summary> public static IList<NamedColor> NamedColorList { private set; get; } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Instance //////////////////////////////////////////////////////////////////////////////// Public #region 명칭 - Name /// <summary> /// 명칭 /// </summary> public string Name { private set; get; } #endregion #region 친숙한 명칭 - FriendlyName /// <summary> /// 친숙한 명칭 /// </summary> public string FriendlyName { private set; get; } #endregion #region 색상 - Color /// <summary> /// 색상 /// </summary> public Color Color { private set; get; } #endregion #region RGB 디스플레이 - RGBDisplay /// <summary> /// RGB 디스플레이 /// </summary> public string RGBDisplay { private set; get; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Static #region 생성자 - NamedColor() /// <summary> /// 생성자 /// </summary> static NamedColor() { List<NamedColor> namedColorList = new List<NamedColor>(); StringBuilder stringBuilder = new StringBuilder(); foreach(FieldInfo fieldInfo in typeof(Colors).GetRuntimeFields()) { if(fieldInfo.IsPublic && fieldInfo.IsStatic && fieldInfo.FieldType == typeof(Color)) { string name = fieldInfo.Name; stringBuilder.Clear(); int index = 0; foreach(char character in name) { if(index != 0 && Char.IsUpper(character)) { stringBuilder.Append(' '); } stringBuilder.Append(character); index++; } Color color = (Color)fieldInfo.GetValue(null); NamedColor namedColor = new NamedColor { Name = name, FriendlyName = stringBuilder.ToString(), Color = color, RGBDisplay = string.Format ( "{0:X2}-{1:X2}-{2:X2}", (int)(255 * color.Red ), (int)(255 * color.Green), (int)(255 * color.Blue ) ) }; namedColorList.Add(namedColor); } } namedColorList.TrimExcess(); namedColorList.Sort(); NamedColorList = namedColorList; } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Instance //////////////////////////////////////////////////////////////////////////////// Private #region 생성자 - NamedColor() /// <summary> /// 생성자 /// </summary> private NamedColor() { } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 찾기 - Find(name) /// <summary> /// 찾기 /// </summary> /// <param name="name">명칭</param> /// <returns>이름있는 색상</returns> public static NamedColor Find(string name) { return ((List<NamedColor>)NamedColorList).Find(nc => nc.Name == name); } #endregion #region 최근접 색상명 구하기 - GetNearestColorName(color) /// <summary> /// 최근접 색상명 구하기 /// </summary> /// <param name="color">색상</param> /// <returns>최근접 색상명</returns> public static string GetNearestColorName(Color color) { double shortestDistance = 1000; NamedColor closestColor = null; foreach(NamedColor namedColor in NamedColor.NamedColorList) { double distance = Math.Sqrt ( Math.Pow(color.Red - namedColor.Color.Red , 2) + Math.Pow(color.Green - namedColor.Color.Green, 2) + Math.Pow(color.Blue - namedColor.Color.Blue , 2) ); if(distance < shortestDistance) { shortestDistance = distance; closestColor = namedColor; } } return closestColor.Name; } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Instance //////////////////////////////////////////////////////////////////////////////// Public #region 동일 여부 구하기 - Equals(other) /// <summary> /// 동일 여부 구하기 /// </summary> /// <param name="other">다른 이름있는 색상</param> /// <returns>동일 여부</returns> public bool Equals(NamedColor other) { return Name.Equals(other.Name); } #endregion #region 비교하기 - CompareTo(other) /// <summary> /// 비교하기 /// </summary> /// <param name="other">다른 이름있는 색상</param> /// <returns>비교 결과</returns> public int CompareTo(NamedColor other) { return Name.CompareTo(other.Name); } #endregion } |
▶ FloatToIntegerConverter.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
using System.Globalization; namespace TestProject; /// <summary> /// 단정도 실수↔정수 변환자 /// </summary> public class FloatToIntegerConverter : IValueConverter { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 변환하기 - Convert(sourceValue, targetType, parameter, cultureInfo) /// <summary> /// 변환하기 /// </summary> /// <param name="sourceValue">소스 값</param> /// <param name="targetType">타겟 타입</param> /// <param name="parameter">매개 변수</param> /// <param name="cultureInfo">문화 정보</param> /// <returns>변환 값</returns> public object Convert(object sourceValue, Type targetType, object parameter, CultureInfo cultureInfo) { return (int)Math.Round((float)sourceValue * GetParameter(parameter)); } #endregion #region 역변환하기 - ConvertBack(sourceValue, targetType, parameter, cultureInfo) /// <summary> /// 역변환하기 /// </summary> /// <param name="sourceValue">소스 값</param> /// <param name="targetType">타겟 타입</param> /// <param name="parameter">매개 변수</param> /// <param name="cultureInfo">문화 정보</param> /// <returns>역변환 값</returns> public object ConvertBack(object sourceValue, Type targetType, object parameter, CultureInfo cultureInfo) { return (int)sourceValue / GetParameter(parameter); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 매개 변수 구하기 - GetParameter(parameter) /// <summary> /// 매개 변수 구하기 /// </summary> /// <param name="parameter">매개 변수</param> /// <returns>매개 변수</returns> private double GetParameter(object parameter) { if(parameter is float) { return (float)parameter; } else if(parameter is int) { return (int)parameter; } else if(parameter is string) { return float.Parse((string)parameter); } return 1; } #endregion } |
▶ RGBColorViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
using System.ComponentModel; namespace TestProject; /// <summary> /// RGB 색상 뷰 모델 /// </summary> public class RGBColorViewModel : INotifyPropertyChanged { //////////////////////////////////////////////////////////////////////////////////////////////////// Event ////////////////////////////////////////////////////////////////////////////////////////// Public #region 속성 변경시 - PropertyChanged /// <summary> /// 속성 변경시 /// </summary> public event PropertyChangedEventHandler PropertyChanged; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 색상 /// </summary> private Color color; /// <summary> /// 명칭 /// </summary> private string name; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 적색 - Red /// <summary> /// 적색 /// </summary> public float Red { get { return this.color.Red; } set { if(this.color.Red != value) { Color = new Color(value, this.color.Green, this.color.Blue); } } } #endregion #region 녹색 - Green /// <summary> /// 녹색 /// </summary> public float Green { get { return this.color.Green; } set { if(this.color.Green != value) { Color = new Color(this.color.Red, value, this.color.Blue); } } } #endregion #region 청색 - Blue /// <summary> /// 청색 /// </summary> public float Blue { get { return this.color.Blue; } set { if(this.color.Blue != value) { Color = new Color(this.color.Red, this.color.Green, value); } } } #endregion #region 색상 - Color /// <summary> /// 색상 /// </summary> public Color Color { get { return this.color; } set { if(this.color != value) { this.color = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Red" )); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Green")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Blue" )); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color")); Name = NamedColor.GetNearestColorName(this.color); } } } #endregion #region 명칭 - Name /// <summary> /// 명칭 /// </summary> public string Name { get { return this.name; } private set { if(this.name != value) { this.name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name")); } } } #endregion } |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestProject" x:DataType="local:RGBColorViewModel"> <ContentPage.BindingContext> <local:RGBColorViewModel Color="Orange" /> </ContentPage.BindingContext> <ContentPage.Resources> <Style TargetType="Slider"> <Setter Property="VerticalOptions" Value="Center" /> </Style> <Style TargetType="Label"> <Setter Property="HorizontalTextAlignment" Value="Center" /> </Style> <local:FloatToIntegerConverter x:Key="FloatToIntegerConverterKey" /> </ContentPage.Resources> <StackLayout HorizontalOptions="Center" VerticalOptions="Center"> <BoxView Color="{Binding Color}" HeightRequest="300" WidthRequest="300" HorizontalOptions="Center" /> <StackLayout Margin="0,10,0,0" x:DataType="{x:Null}"> <Label Text="{Binding Name}" /> <Slider Margin="0,30,0,0" Value="{Binding Red}" /> <Label Text="{Binding Red, Converter={StaticResource FloatToIntegerConverterKey}, ConverterParameter=255, StringFormat='적색 : {0:X2}'}" /> <Slider Margin="0,10,0,0" Value="{Binding Green}" /> <Label Text="{Binding Green, Converter={StaticResource FloatToIntegerConverterKey}, ConverterParameter=255, StringFormat='녹색 : {0:X2}'}" /> <Slider Margin="0,10,0,0" Value="{Binding Blue}" /> <Label> <Label.Text> <Binding Path="Blue" StringFormat="청색 : {0:X2}" Converter="{StaticResource FloatToIntegerConverterKey}"> <Binding.ConverterParameter> <x:Single>255</x:Single> </Binding.ConverterParameter> </Binding> </Label.Text> </Label> </StackLayout> </StackLayout> </ContentPage> |