하아찡

[C#/WPF/수정] PublicColor프로젝트 색변경 추가 본문

C#/코인프로그램 - 코드

[C#/WPF/수정] PublicColor프로젝트 색변경 추가

하아찡 2023. 12. 6. 21:45

 

 

 

ColorView.xaml

<UserControl x:Class="PublicColor.View.ColorView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker"
             xmlns:local="clr-namespace:PublicColor.View"
             xmlns:vm="clr-namespace:PublicColor.Model"
             mc:Ignorable="d" >
    <UserControl.DataContext>
        <vm:ColorModel/>
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>
        <ListView Grid.Row="0" ItemsSource="{Binding MyColors}">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="BorderThickness" Value="0"/>
                    <Setter Property="Margin" Value="0"/>
                    <Setter Property="Padding" Value="2"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding Name}" HorizontalAlignment="Left"/>
                        <colorpicker:PortableColorPicker  SelectedColor="{Binding Clr}" HorizontalAlignment="Right"  ColorState="{Binding ClrState, Mode=TwoWay}" Width="50" Height="20"/>    
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button Grid.Row="1" Command="{Binding CommandSaveColors}" Content="저장"/>


    </Grid>
</UserControl>

해당 ColorPicker는 Nuget에서 PixiEditor.ColorPicker추가하여 사용했습니다.

 

 

ColorModel.cs

using ColorPicker.Models;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using static System.Net.Mime.MediaTypeNames;

namespace PublicColor.Model
{
    public class StructColor : BindableBase
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { SetProperty(ref name, value); }
        }
        private string key;
        public string Key
        {
            get { return key; }
            set { SetProperty(ref key, value); }
        }

        private bool ischanged;
        public bool IsChanged
        {
            get
            {
                return ischanged;
            }
            set
            {
                SetProperty(ref ischanged, value);
            }
        }
        private string precolor;
        public string PreColor
        {
            get { return precolor; }
            set { SetProperty(ref precolor, value); }
        }

        private string nowcolor;
        public string NowColor
        {
            get { return nowcolor; }
            set { SetProperty(ref nowcolor, value); }
        }
        private ColorState clrstate;
        public ColorState ClrState
        {
            get { return clrstate; }
            set { SetProperty(ref clrstate, value); }
        }
        private Color clr;
        public Color Clr
        {
            get { return clr; }
            set { SetProperty(ref clr, value); }
        }
    }
    public class ColorModel : BindableBase
    {
        #region Model
        private List<StructColor> mycolors;
        public List<StructColor> MyColors
        {
            get { return mycolors; }
            set { SetProperty(ref mycolors, value); }
        }
        //Colors.cs에서 color값을 받아와서 현재 View에 저장
        private Dictionary<string, string> diccolors;
        public Dictionary<string, string> DicColors
        {
            get { return diccolors; }
            set { SetProperty(ref diccolors, value); }
        }


        #endregion Model

        #region Events
        private DelegateCommand commandsavecolors;
        public DelegateCommand CommandSaveColors =>
            commandsavecolors ?? (commandsavecolors = new DelegateCommand(ExecuteCommandSaveColors));

        void ExecuteCommandSaveColors()
        {
            for(int i = 0; i < MyColors.Count; i++) 
            {
                MyColors[i].NowColor = ColorToString(ColorStateToColor(MyColors[i].ClrState));
                if (MyColors[i].NowColor != MyColors[i].PreColor)
                    MyColors[i].IsChanged = true;
            }
            bool _b = false;
            foreach(var v in MyColors)
            {
                if (v.IsChanged)
                {
                    _b = true;
                    PublicColor.Colors.Colorinstance.SetColor(v.Key, v.NowColor);
                }
            }
            if (_b)
            {
                PublicColor.Colors.Colorinstance.SetColor();
                MessageBox.Show("변경완료");
            }
        }

        #endregion Events

        #region Functions
        /// <summary>
        /// DirColors값을 받아옴.
        /// </summary>
        private Dictionary<string, string> GetColors()
        {
            return PublicColor.Colors.Colorinstance.DirColors;
        }

        private ColorState StringToColorState(string color)
        {
            ColorState val = new ColorState();
            Color clr = StringToColor(color);
            val.RGB_R = clr.R / 255.0;
            val.RGB_G = clr.G / 255.0;
            val.RGB_B = clr.B / 255.0;
            val.A = clr.A / 255.0;

            return val;
        }

        private Color ColorStateToColor(ColorState cst)
        {
            Color val = new Color();
            val.R = (byte)Math.Round(255 * cst.RGB_R);
            val.G = (byte)Math.Round(255 * cst.RGB_G);
            val.B = (byte)Math.Round(255 * cst.RGB_B);
            val.A = (byte)Math.Round(255 * cst.A);

            return val;
        }

        private Color StringToColor(string color)
        {
            Color clr;
            byte A = Convert.ToByte((color[0].ToString() + color[1].ToString()), 16);
            byte R = Convert.ToByte((color[2].ToString() + color[3].ToString()), 16);
            byte G = Convert.ToByte((color[4].ToString() + color[5].ToString()), 16);
            byte B = Convert.ToByte((color[6].ToString() + color[7].ToString()), 16);
            clr = Color.FromArgb(
                    A,
                    R,
                    G,
                    B);

            return clr;
        }

        private Brush ColorToBrush(Color clr)
        {
            Brush br;
            var bc = new BrushConverter();

            return (Brush)bc.ConvertFrom($"#{ColorToString(clr)}");
        }

        private string ColorToString(Color clr)
        {
            string val = "";
            byte A = clr.A;
            byte G = clr.G;
            byte B = clr.B;
            byte R = clr.R;
            val = $"{A:X2}{R:X2}{G:X2}{B:X2}";

            return val;
        }
        #endregion Functions


        public ColorModel()
        {
            DicColors = GetColors();
            MyColors = new List<StructColor>();
            foreach (KeyValuePair<string,string> k in DicColors)
            {
                StructColor st = new StructColor();
                st.Name = k.Key;
                st.PreColor = k.Value;
                st.NowColor = k.Value;
                st.Key = k.Key;
                st.Clr = StringToColor(k.Value);
                st.IsChanged = false;
                st.ClrState = StringToColorState(k.Value);
                MyColors.Add(st);
            }

        }
    }
}

 

ColorPicker를 사용하는데 있어서 문제는 현재 색상 처리방식은 Brush로 처리하고 저장은 "#FFFFFFFF"이런식으로 저장하여 변환해서 사용했는데 ColorPicker에서 ColorState에 데이터를 바인딩시킬땐 ColorState를 사용해야해서 내가 가진 색상값을 변경해줘야 함.

그래서 생성자쪽을보면 내가 가진 컬러값을 아래 코드로 정제시키는 과정을 진행함.

foreach (KeyValuePair<string,string> k in DicColors)
{
    StructColor st = new StructColor();
    st.Name = k.Key;
    st.PreColor = k.Value;
    st.NowColor = k.Value;
    st.Key = k.Key;
    st.Clr = StringToColor(k.Value);
    st.IsChanged = false;
    st.ClrState = StringToColorState(k.Value);
    MyColors.Add(st);
}

위 코드는 내가 가진 색상값을 UI쪽에서 사용하기위해 데이터를 가공함.

 

private ColorState StringToColorState(string color)
{
    ColorState val = new ColorState();
    Color clr = StringToColor(color);
    val.RGB_R = clr.R / 255.0;
    val.RGB_G = clr.G / 255.0;
    val.RGB_B = clr.B / 255.0;
    val.A = clr.A / 255.0;

    return val;
}

StringToColorState함수를 호출하는데 문자열로 저장한 색상값 정수를 실수로 변경하는 과정이 들어감.

내 "색상값 / 255" 즉, 0~1 사이의 값으로 변환.

 

해당 ColorPicker에서 ColorChanged 이벤트가 있는데 Mvvm패턴을 사용해서 사용하는 방법을 몰라서 버튼을 눌렀을때 데이터를 저장하는 방식으로 사용하였습니다.

 

private DelegateCommand commandsavecolors;
public DelegateCommand CommandSaveColors =>
    commandsavecolors ?? (commandsavecolors = new DelegateCommand(ExecuteCommandSaveColors));

void ExecuteCommandSaveColors()
{
    for(int i = 0; i < MyColors.Count; i++) 
    {
        MyColors[i].NowColor = ColorToString(ColorStateToColor(MyColors[i].ClrState));
        if (MyColors[i].NowColor != MyColors[i].PreColor)
            MyColors[i].IsChanged = true;
    }
    bool _b = false;
    foreach(var v in MyColors)
    {
        if (v.IsChanged)
        {
            _b = true;
            PublicColor.Colors.Colorinstance.SetColor(v.Key, v.NowColor);
        }
    }
    if (_b)
    {
        PublicColor.Colors.Colorinstance.SetColor();
        MessageBox.Show("변경완료");
    }
}

구조를 만들때 저장되기 전값과 현재값을 동시에 저장해놓고 색을 변경했을때 현재값을 변경하는 방식을 사용해서 변경된 데이터만 따로 수정해서 저장함.

 

반응형