💻 ComboBoxColorManager
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using WpfLib.Controls;
using WpfLib.Extensions;
namespace WpfLib.Commons
{
public class ComboBoxColorManager
{
// Fields
private static Brush? _newBackground;
private static Brush? _newBorderBrush;
// Properties
public static readonly DependencyProperty BackgroundProperty =
DependencyProperty.RegisterAttached("Background", typeof(Brush), typeof(ComboBoxColorManager), new UIPropertyMetadata(null, BackgroundChanged));
public static readonly DependencyProperty BorderBrushProperty =
DependencyProperty.RegisterAttached("BorderBrush", typeof(Brush), typeof(ComboBoxColorManager), new UIPropertyMetadata(null, BorderBrushChanged));
// Methods
private static void AddEvents(DependencyObject d, DependencyPropertyChangedEventArgs e, Action<Brush> brushCallBack)
{
ComboBox? cmb = d as ComboBox;
if (cmb == null) return;
if (e.NewValue != e.OldValue)
{
brushCallBack?.Invoke((Brush)e.NewValue);
cmb.Loaded -= Cmb_Loaded;
cmb.Unloaded -= Cmb_Unloaded;
cmb.Loaded += Cmb_Loaded;
cmb.Unloaded += Cmb_Unloaded;
}
}
public static Brush GetBackground(DependencyObject obj)
{
return (Brush)obj.GetValue(BackgroundProperty);
}
public static void SetBackground(DependencyObject obj, Brush value)
{
obj.SetValue(BackgroundProperty, value);
}
public static Brush GetBorderBrush(DependencyObject obj)
{
return (Brush)obj.GetValue(BorderBrushProperty);
}
public static void SetBorderBrush(DependencyObject obj, Brush value)
{
obj.SetValue(BorderBrushProperty, value);
}
// Events
private static void BackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AddEvents(d, e, brush => _newBackground = brush);
}
private static void BorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
AddEvents(d, e, brush => _newBorderBrush = brush);
}
private static void Cmb_Unloaded(object sender, RoutedEventArgs e)
{
ComboBox? cmb = (ComboBox)sender;
cmb.Loaded -= Cmb_Loaded;
cmb.Unloaded -= Cmb_Unloaded;
_newBackground = null;
_newBorderBrush = null;
}
private static void Cmb_Loaded(object sender, RoutedEventArgs e)
{
ComboBox? cmb = (ComboBox)sender;
if (_newBackground != null)
{
cmb.SetBackground(_newBackground);
}
if (_newBorderBrush != null)
{
cmb.SetBorderBrush(_newBorderBrush);
}
}
}
}
💻 ComboBoxControl
<UserControl x:Class="WpfLib.Controls.ComboBoxControl"
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:local="clr-namespace:WpfLib.Controls"
xmlns:converters="clr-namespace:WpfLib.Converters"
xmlns:commons="clr-namespace:WpfLib.Commons"
mc:Ignorable="d"
Name="root"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<converters:ValidatingBorderBrushConverter x:Key="ValidatingBorderBrushConverter"/>
<converters:ValidatingBorderThicknessConverter x:Key="ValidatingBorderThicknessConverter"/>
<Style x:Key="BaseControl" TargetType="{x:Type FrameworkElement}">
<Setter Property="Control.FontSize" Value="{Binding FontSize, ElementName=root}"/>
<Setter Property="Control.FontFamily" Value="{Binding FontFamily, ElementName=root}"/>
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseControl}">
<Setter Property="Text" Value="{Binding WaterMarkText, ElementName=root}"/>
<Setter Property="Foreground" Value="{Binding WaterMarkTextColor, ElementName=root}"/>
<Setter Property="Padding" Value="5 0 0 0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=cmb}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseControl}">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="IsEditable" Value="{Binding IsEditable, ElementName=root}"/>
<Setter Property="Text" Value="{Binding Text, ElementName=root, UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="SelectedItem" Value="{Binding SelectedItem, ElementName=root}"/>
<Setter Property="SelectedIndex" Value="{Binding SelectedIndex, ElementName=root}"/>
<Setter Property="ItemsSource" Value="{Binding ItemsSource, ElementName=root}"/>
<Setter Property="ItemContainerStyle" Value="{Binding ItemContainerStyle, ElementName=root}"/>
<Setter Property="commons:ComboBoxColorManager.Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness">
<Setter.Value>
<MultiBinding Converter="{StaticResource ValidatingBorderThicknessConverter}">
<Binding Path="Validating" ElementName="root"/>
<Binding Path="BorderThickness" ElementName="root"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<MultiBinding Converter="{StaticResource ValidatingBorderBrushConverter}">
<Binding Path="Validating" ElementName="root"/>
<Binding Path="BorderBrush" ElementName="root"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<TextBlock x:Name="txt"/>
<Border>
<ComboBox x:Name="cmb"/>
</Border>
</Grid>
</UserControl>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfLib.Controls
{
/// <summary>
/// ComboBoxControl.xaml에 대한 상호 작용 논리
/// </summary>
public partial class ComboBoxControl : UserControl
{
public ComboBoxControl()
{
InitializeComponent();
}
#region Static Properties
public static readonly DependencyProperty IsEditableProperty =
DependencyProperty.Register("IsEditable", typeof(bool), typeof(ComboBoxControl), new PropertyMetadata(null));
public static readonly DependencyProperty ValidatingProperty =
DependencyProperty.Register("Validating", typeof(bool), typeof(ComboBoxControl), new PropertyMetadata(null));
public static new readonly DependencyProperty BorderBrushProperty =
DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(ComboBoxControl), new UIPropertyMetadata(Brushes.SkyBlue));
public static new readonly DependencyProperty BorderThicknessProperty =
DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(ComboBoxControl), new UIPropertyMetadata(new Thickness(1)));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ComboBoxControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty WaterMarkTextProperty =
DependencyProperty.Register("WaterMarkText", typeof(string), typeof(ComboBoxControl), new PropertyMetadata(null));
public static readonly DependencyProperty WaterMarkTextColorProperty =
DependencyProperty.Register("WaterMarkTextColor", typeof(Brush), typeof(ComboBoxControl), new UIPropertyMetadata(Brushes.Gray));
public static readonly DependencyProperty ItemContainerStyleProperty =
DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(ComboBoxControl), new PropertyMetadata(null));
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(ComboBoxControl), new PropertyMetadata(null));
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(ComboBoxControl), new PropertyMetadata(null));
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(ComboBoxControl), new PropertyMetadata(null));
#endregion
#region Public Properties
public bool IsEditable
{
get { return (bool)GetValue(IsEditableProperty); }
set { SetValue(IsEditableProperty, value); }
}
public bool Validating
{
get { return (bool)GetValue(ValidatingProperty); }
set { SetValue(ValidatingProperty, value); }
}
public new Brush BorderBrush
{
get { return (Brush)GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
}
public new Thickness BorderThickness
{
get { return (Thickness)GetValue(BorderThicknessProperty); }
set { SetValue(BorderThicknessProperty, value); }
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public string WaterMarkText
{
get { return (string)GetValue(WaterMarkTextProperty); }
set { SetValue(WaterMarkTextProperty, value); }
}
public Brush WaterMarkTextColor
{
get { return (Brush)GetValue(WaterMarkTextColorProperty); }
set { SetValue(WaterMarkTextColorProperty, value); }
}
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public Style ItemContainerStyle
{
get { return (Style)GetValue(ItemContainerStyleProperty); }
set { SetValue(ItemContainerStyleProperty, value); }
}
public object SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public int SelectedIndex
{
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
#endregion
}
}
💻 ComboBoxExtensions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace WpfLib.Extensions
{
public static class ComboBoxExtensions
{
public static Border? GetBorder(this ComboBox comboBox)
{
ToggleButton? toggleButton = (ToggleButton?)comboBox.Template?.FindName("toggleButton", comboBox);
return (Border?)toggleButton?.Template?.FindName("templateRoot", toggleButton);
}
public static void SetBorderBrush(this ComboBox comboBox, Brush brush)
{
Border? border = comboBox.GetBorder();
if (border != null)
border.BorderBrush = brush;
}
public static void SetBackground(this ComboBox comboBox, Brush brush)
{
Border? border = comboBox.GetBorder();
if (border != null)
border.Background = brush;
TextBox? textbox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", comboBox);
if (textbox != null)
{
Border? parent = (Border)textbox.Parent;
parent.Background = brush;
}
}
}
}
💻 LoginControl에 콤보박스 추가하기
<controls:ComboBoxControl Background="White" Height="35"
WaterMarkText="이메일을 입력하세요."
WaterMarkTextColor="Blue"
IsEditable="True"
BorderBrush="Red"
ItemsSource="{Binding Emails}"/>
💻 LoginViewModel에 테스트 이메일 데이터 추가를 해준다
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SunjeongTalk.ViewModels
{
[ObservableObject]
public partial class LoginControlViewModel
{
[ObservableProperty]
private ObservableCollection<string> _emails;
public LoginControlViewModel()
{
Emails = new ObservableCollection<string>()
{
"test1@test1.com",
"test2@test2.com"
};
}
}
}
'C# > WPF' 카테고리의 다른 글
[WPF] Dependency Injection(DI) IoC를 이용한 ViewModel간 데이터 전달 (0) | 2023.08.23 |
---|---|
[WPF] Dependency Injection(DI) IoC 를 이용한 Navigation (0) | 2023.08.23 |
[WPF] 카카오톡 구현 6 - ComboBox BackGround 변경하기 (1) | 2023.08.22 |
[WPF] 카카오톡 구현 5 - PasswordBox WaterMarkText, Validating 만들어보기 (0) | 2023.08.22 |
[WPF] 카카오톡 구현하기 4 - TextBox WaterMarkText, Validating 만들어보기 (0) | 2023.08.21 |