728x90
반응형
728x170
■ x:DataType 속성에서 컴파일된 바인딩과 클래식 바인딩을 함께 사용하는 방법을 보여준다.
▶ NamedColor.cs
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
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
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
<?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>
728x90
반응형
그리드형(광고전용)
'C# > MAUI' 카테고리의 다른 글
[C#/MAUI/.NET6] SwipeGestureRecognizer 클래스 : Swiped 이벤트를 사용해 스와이프 처리하기 (0) | 2022.03.18 |
---|---|
[C#/MAUI/.NET6] PinchGestureRecognizer 클래스 : PinchUpdated 업데이트를 사용해 핀치 처리하기 (0) | 2022.03.18 |
[C#/MAUI/.NET6] PanGestureRecognizer 클래스 : PanUpdated 이벤트를 사용해 패닝 처리하기 (0) | 2022.03.18 |
[C#/MAUI/.NET6] DeviceDisplay 클래스 : MainDisplayInfo 속성을 사용해 화면 크기 구하기 (0) | 2022.03.18 |
[C#/MAUI/.NET6] DragGestureRecognizer 클래스 : DragStarting 이벤트를 사용해 드래그 시작시 처리하기 (0) | 2022.03.17 |
[C#/MAUI/.NET6] x:DataType 속성 : DataTemplate 엘리먼트에서 사용하기 (0) | 2022.03.13 |
[C#/MAUI/.NET6] x:DataType 속성 : 컴파일된 바인딩 사용하기 (0) | 2022.03.13 |
[C#/MAUI/.NET6] MultiBinding 클래스 : StringFormat 속성 사용하기 (0) | 2022.03.13 |
[C#/MAUI/.NET6] MultiBinding 엘리먼트 : StringFormat 속성 사용하기 (0) | 2022.03.13 |
[C#/MAUI/.NET6] MultiBinding 클래스 : Converter 속성 사용하기 (0) | 2022.03.13 |
댓글을 달아 주세요