728x90
반응형
728x170
[TestLibrary 프로젝트]
▶ MenuButton.xaml
<UserControl x:Class="TestLibrary.MenuButton"
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:TestLibrary"
mc:Ignorable="d"
d:DesignWidth="300"
d:DesignHeight="300">
<Grid Name="rootGrid">
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="25" />
</Grid.ColumnDefinitions>
<Grid Name="triggerGrid" Grid.Row="0" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Name="image" Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
Margin="15 10"
MaxHeight="20" />
<Label Name="textLabel" Grid.Row="0" Grid.Column="1"
VerticalAlignment="Stretch"
VerticalContentAlignment="Center"
Content="{Binding Text}" />
</Grid>
<Image Name="chevronImage" Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Left"
Width="15"
Source="IMAGE/Light24.png">
<Image.RenderTransform>
<RotateTransform x:Name="chevronRotateTransform"
CenterX="7.5"
CenterY="7.5"/>
</Image.RenderTransform>
</Image>
<ItemsControl Name="childItemsControl" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Height="0"
ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:MenuButton
Height="30"
Image="{Binding Image}"
Text="{Binding Text}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
728x90
▶ MenuButton.xaml.cs
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
namespace TestLibrary
{
/// <summary>
/// 메뉴 버튼
/// </summary>
public partial class MenuButton
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region UI 테마 속성 - UIThemeProperty
/// <summary>
/// UI 테마 속성
/// </summary>
public static readonly DependencyProperty UIThemeProperty = DependencyProperty.Register
(
"UITheme",
typeof(UITheme),
typeof(MenuButton)
);
#endregion
#region HOVER 배경 속성 - HoverBackgroundProperty
/// <summary>
/// HOVER 배경 속성
/// </summary>
public static readonly DependencyProperty HoverBackgroundProperty = DependencyProperty.Register
(
"HoverBackground",
typeof(SolidColorBrush),
typeof(MenuButton)
);
#endregion
#region 애니메이션 속도 속성 - AnimationSpeedProperty
/// <summary>
/// 애니메이션 속도 속성
/// </summary>
public static readonly DependencyProperty AnimationSpeedProperty = DependencyProperty.Register
(
"AnimationSpeed",
typeof(TimeSpan),
typeof(MenuButton)
);
#endregion
#region 이미지 속성 - ImageProperty
/// <summary>
/// 이미지 속성
/// </summary>
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register
(
"Image",
typeof(ImageSource),
typeof(MenuButton)
);
#endregion
#region 텍스트 속성 - TextProperty
/// <summary>
/// 텍스트 속성
/// </summary>
public static readonly DependencyProperty TextProperty = DependencyProperty.Register
(
"Text",
typeof(string),
typeof(MenuButton)
);
#endregion
#region 자식 리스트 속성 - ChildrenProperty
/// <summary>
/// 자식 리스트 속성
/// </summary>
public static readonly DependencyProperty ChildrenProperty = DependencyProperty.Register
(
"Children",
typeof(List<MenuButton>),
typeof(MenuButton)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 자식 표시 여부
/// </summary>
private bool childrenVisible;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 테마 - Theme
/// <summary>
/// 테마
/// </summary>
public UITheme Theme
{
get
{
return (UITheme)GetValue(UIThemeProperty);
}
set
{
SetValue(UIThemeProperty, value);
BitmapImage bitmapImage;
switch(Theme)
{
case UITheme.Light :
bitmapImage = new BitmapImage(new Uri(@"IMAGE/Light24.png", UriKind.Relative));
break;
case UITheme.Dark :
bitmapImage = new BitmapImage(new Uri(@"IMAGE/Dark24.png", UriKind.Relative));
break;
default :
throw new ArgumentOutOfRangeException();
}
Image image = FindName("chevronImage") as Image;
image.Source = bitmapImage;
Label textLabel = FindName("textLabel") as Label;
if(Theme == UITheme.Light)
{
textLabel.Foreground = Brushes.WhiteSmoke;
}
else
{
textLabel.Foreground = new SolidColorBrush { Color = Color.FromRgb(30, 30, 30) };
}
}
}
#endregion
#region HOVER 배경 - HoverBackground
/// <summary>
/// HOVER 배경
/// </summary>
public SolidColorBrush HoverBackground
{
get
{
return (SolidColorBrush)GetValue(HoverBackgroundProperty);
}
set
{
SetValue(HoverBackgroundProperty, value);
}
}
#endregion
#region 애니메이션 속도 - AnimationSpeed
/// <summary>
/// 애니메이션 속도
/// </summary>
public TimeSpan AnimationSpeed
{
get
{
return (TimeSpan)GetValue(AnimationSpeedProperty);
}
set
{
SetValue(AnimationSpeedProperty, value);
}
}
#endregion
#region 이미지 - Image
/// <summary>
/// 이미지
/// </summary>
public ImageSource Image
{
get
{
return (ImageSource)GetValue(ImageProperty);
}
set
{
SetValue(ImageProperty, value);
}
}
#endregion
#region 텍스트 - Text
/// <summary>
/// 텍스트
/// </summary>
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
#endregion
#region 자식 리스트 - Children
/// <summary>
/// 자식 리스트
/// </summary>
public List<MenuButton> Children
{
get
{
return (List<MenuButton>)GetValue(ChildrenProperty);
}
set
{
SetValue(ChildrenProperty, value);
foreach(MenuButton child in Children)
{
child.ParentButton = this;
}
DataContext = Children;
Image chevronImage = FindName("chevronImage") as Image;
if(Children == null || Children.Count == 0)
{
chevronImage.Visibility = Visibility.Hidden;
}
else
{
chevronImage.Visibility = Visibility.Visible;
}
}
}
#endregion
#region 부모 버튼 - ParentButton
/// <summary>
/// 부모 버튼
/// </summary>
public MenuButton ParentButton { get; private set; }
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 확장 높이 - ExpandedHeight
/// <summary>
/// 확장 높이
/// </summary>
private double ExpandedHeight => Children.Count * ActualHeight + 5;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MenuButton()
/// <summary>
/// 생성자
/// </summary>
public MenuButton()
{
InitializeComponent();
Children = new List<MenuButton>();
Theme = UITheme.Light;
AnimationSpeed = TimeSpan.FromMilliseconds(150);
MouseEnter += UserControl_MouseEnter;
MouseLeave += UserControl_MouseLeave;
this.triggerGrid.MouseDown += UserControl_MouseDown;
this.chevronImage.MouseDown += UserControl_MouseDown;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 템플리트 적용시 처리하기 - OnApplyTemplate()
/// <summary>
/// 템플리트 적용시 처리하기
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Label textLabel = FindName("textLabel") as Label;
textLabel.Content = Text;
Image image = FindName("image") as Image;
image.Source = Image;
ItemsControl childItemsControl = FindName("childItemsControl") as ItemsControl;
childItemsControl.DataContext = Children;
childItemsControl.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateTarget();
foreach(MenuButton child in Children)
{
child.ParentButton = this;
}
Image chevronImage = FindName("chevronImage") as Image;
if(Children == null || Children.Count == 0)
{
chevronImage.Visibility = Visibility.Hidden;
}
else
{
chevronImage.Visibility = Visibility.Visible;
}
Grid rootGrid = FindName("rootGrid") as Grid;
rootGrid.Background = Background;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 초기화시 처리하기 - OnInitialized(e)
/// <summary>
/// 초기화시 처리하기
/// </summary>
/// <param name="e">이벤트 인자</param>
protected override void OnInitialized(EventArgs e)
{
InitializeComponent();
base.OnInitialized(e);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 사용자 컨트롤 마우스 진입시 처리하기 - UserControl_MouseEnter(sender, e)
/// <summary>
/// 사용자 컨트롤 마우스 진입시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
Grid rootGrid = FindName("rootGrid") as Grid;
ColorAnimation animation = new ColorAnimation
{
To = HoverBackground.Color,
Duration = AnimationSpeed
};
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTarget (animation, rootGrid);
Storyboard.SetTargetProperty(animation, new PropertyPath("Background.Color"));
storyboard.Begin();
}
#endregion
#region 사용자 컨트롤 마우스 이탈시 처리하기 - UserControl_MouseLeave(sender, e)
/// <summary>
/// 사용자 컨트롤 마우스 이탈시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
Grid rootGrid = FindName("rootGrid") as Grid;
ColorAnimation animation = new ColorAnimation
{
To = (Background as SolidColorBrush).Color,
Duration = AnimationSpeed
};
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
Storyboard.SetTarget (animation, rootGrid);
Storyboard.SetTargetProperty(animation, new PropertyPath("Background.Color"));
storyboard.Begin();
}
#endregion
#region 사용자 컨트롤 마우스 DOWN 처리하기 - UserControl_MouseDown(sender, e)
/// <summary>
/// 사용자 컨트롤 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
{
if(Children.Count == 0)
{
return;
}
if(this.childrenVisible)
{
MenuButton parent = ParentButton;
while(parent != null)
{
ItemsControl childItemsControl = FindName("childItemsControl") as ItemsControl;
parent.Reduce(childItemsControl.ActualHeight);
parent = parent.ParentButton;
}
Close();
}
else
{
MenuButton parent = ParentButton;
while(parent != null)
{
parent.Expand(ExpandedHeight);
parent = parent.ParentButton;
}
Open();
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 확장하기 - Expand(height)
/// <summary>
/// 확장하기
/// </summary>
/// <param name="height">높이</param>
private void Expand(double height)
{
ItemsControl childItemsControl = FindName("childItemsControl") as ItemsControl;
DoubleAnimation animation = new DoubleAnimation
{
From = childItemsControl.ActualHeight,
To = childItemsControl.ActualHeight + height,
Duration = AnimationSpeed
};
childItemsControl.BeginAnimation(HeightProperty, animation);
}
#endregion
#region 축소하기 - Reduce(height)
/// <summary>
/// 축소하기
/// </summary>
/// <param name="height">높이</param>
private void Reduce(double height)
{
ItemsControl childItemsControl = FindName("childItemsControl") as ItemsControl;
DoubleAnimation animation = new DoubleAnimation
{
From = childItemsControl.ActualHeight,
To = childItemsControl.ActualHeight - height,
Duration = AnimationSpeed
};
childItemsControl.BeginAnimation(HeightProperty, animation);
}
#endregion
#region 열기 - Open()
/// <summary>
/// 열기
/// </summary>
private void Open()
{
RotateTransform chevronRotateTransform = FindName("chevronRotateTransform") as RotateTransform;
DoubleAnimation animation = new DoubleAnimation
{
To = 90,
Duration = AnimationSpeed
};
chevronRotateTransform.BeginAnimation(RotateTransform.AngleProperty, animation);
Expand(ExpandedHeight);
this.childrenVisible = true;
}
#endregion
#region 닫기 - Close()
/// <summary>
/// 닫기
/// </summary>
private void Close()
{
RotateTransform chevronRotateTransform = FindName("chevronRotateTransform") as RotateTransform;
DoubleAnimation angleDoubleAnimation = new DoubleAnimation
{
To = 0,
Duration = AnimationSpeed
};
chevronRotateTransform.BeginAnimation(RotateTransform.AngleProperty, angleDoubleAnimation);
foreach(MenuButton child in Children)
{
child.Close();
}
if(!this.childrenVisible)
{
return;
}
ItemsControl childItemsControl = FindName("childItemsControl") as ItemsControl;
DoubleAnimation heightDoubleAnimation = new DoubleAnimation
{
From = childItemsControl.ActualHeight,
To = 0,
Duration = AnimationSpeed
};
childItemsControl.BeginAnimation(HeightProperty, heightDoubleAnimation);
this.childrenVisible = false;
}
#endregion
#region 배경 설정하기 - SetBackground(background)
/// <summary>
/// 배경 설정하기
/// </summary>
/// <param name="background">배경</param>
public void SetBackground(Brush background)
{
this.rootGrid.Background = background;
}
#endregion
}
}
300x250
▶ SideMenu.xaml
<UserControl Name="userControl" x:Class="TestLibrary.SideMenu"
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:TestLibrary"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="300">
<UserControl.Resources>
<SolidColorBrush x:Key="ButtonBackgroundSolidColorBrushKey"
Color="{Binding ButtonHover, ElementName=userControl}" />
<SolidColorBrush x:Key="ButtonHoverSolidColorBrushKey"
Color="{Binding ButtonBackground, ElementName=userControl}" />
<SolidColorBrush x:Key="ShadowSolidColorBrushKey"
Color="{Binding ShadowBackground, ElementName=userControl}" />
<Style TargetType="local:MenuButton">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundSolidColorBrushKey}" />
<Setter Property="HoverBackground" Value="{DynamicResource ButtonHoverSolidColorBrushKey}" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="menuColumnDefinition" Width="400" />
<ColumnDefinition x:Name="shadowColumnDefinition" Width="0" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
Content="{Binding Menu, ElementName=userControl}" />
<Border Name="shadowBorder" Grid.Column="1"
Background="{DynamicResource ShadowSolidColorBrushKey}" />
</Grid>
</UserControl>
▶ SideMenu.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace TestLibrary
{
/// <summary>
/// 사이드 메뉴
/// </summary>
public partial class SideMenu
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 테마 속성 - ThemeProperty
/// <summary>
/// 테마 속성
/// </summary>
public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register
(
"Theme",
typeof(SideMenuTheme),
typeof(SideMenu)
);
#endregion
#region 상태 속성 - StateProperty
/// <summary>
/// 상태 속성
/// </summary>
public static readonly DependencyProperty StateProperty = DependencyProperty.Register
(
"State",
typeof(MenuState),
typeof(SideMenu)
);
#endregion
#region 메뉴 너비 속성 - MenuWidthProperty
/// <summary>
/// 메뉴 너비 속성
/// </summary>
public static readonly DependencyProperty MenuWidthProperty = DependencyProperty.Register
(
"MenuWidth",
typeof(double),
typeof(SideMenu)
);
#endregion
#region 메뉴 속성 - MenuProperty
/// <summary>
/// 메뉴 속성
/// </summary>
public static readonly DependencyProperty MenuProperty = DependencyProperty.Register
(
"Menu",
typeof(ScrollViewer),
typeof(SideMenu)
);
#endregion
#region 그림자 배경 속성 - ShadowBackgroundProperty
/// <summary>
/// 그림자 배경 속성
/// </summary>
public static readonly DependencyProperty ShadowBackgroundProperty = DependencyProperty.Register
(
"ShadowBackground",
typeof(Brush),
typeof(SideMenu)
);
#endregion
#region 버튼 배경 속성 - ButtonBackgroundProperty
/// <summary>
/// 버튼 배경 속성
/// </summary>
public static readonly DependencyProperty ButtonBackgroundProperty = DependencyProperty.Register
(
"ButtonBackground",
typeof(Brush),
typeof(SideMenu)
);
#endregion
#region 버튼 HOVER 속성 - ButtonHoverProperty
/// <summary>
/// 버튼 HOVER 속성
/// </summary>
public static readonly DependencyProperty ButtonHoverProperty = DependencyProperty.Register
(
"ButtonHover",
typeof(Brush),
typeof(SideMenu)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 표시 여부
/// </summary>
private bool isShown;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 테마 - Theme
/// <summary>
/// 테마
/// </summary>
public SideMenuTheme Theme
{
get
{
return (SideMenuTheme)GetValue(ThemeProperty);
}
set
{
if(value == SideMenuTheme.None)
{
return;
}
SetValue(ThemeProperty, value);
SolidColorBrush buttonBackground;
SolidColorBrush buttonHoverBackground;
SolidColorBrush background;
switch(value)
{
case SideMenuTheme.Default :
background = new SolidColorBrush { Color = Color.FromArgb(205, 20, 20, 20) };
buttonBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 30, 30, 30) };
buttonHoverBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 70, 70, 70) };
break;
case SideMenuTheme.Primary :
background = new SolidColorBrush { Color = Color.FromArgb(205, 24, 57 , 85 ) };
buttonBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 35, 85 , 126) };
buttonHoverBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 45, 110, 163) };
break;
case SideMenuTheme.Success :
background = new SolidColorBrush { Color = Color.FromArgb(205, 55, 109, 55) };
buttonBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 65, 129, 65) };
buttonHoverBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 87, 172, 87) };
break;
case SideMenuTheme.Warning :
background = new SolidColorBrush { Color = Color.FromArgb(205, 150, 108, 49) };
buttonBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 179, 129, 58) };
buttonHoverBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 216, 155, 70) };
break;
case SideMenuTheme.Danger :
background = new SolidColorBrush { Color = Color.FromArgb(205, 135, 52, 49) };
buttonBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 179, 69, 65) };
buttonHoverBackground = new SolidColorBrush { Color = Color.FromArgb(50 , 238, 92, 86) };
break;
default :
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
ButtonBackground = buttonBackground;
ButtonHover = buttonHoverBackground;
if(Menu != null)
{
Menu.Background = background;
StackPanel stackPanel = Menu.Content as StackPanel;
foreach(UIElement child in stackPanel.Children)
{
if(child is MenuButton menuButton)
{
SetMenuButtonBackground(menuButton, buttonBackground, buttonHoverBackground);
}
}
}
}
}
#endregion
#region 상태 - State
/// <summary>
/// 상태
/// </summary>
public MenuState State
{
get
{
return (MenuState)GetValue(StateProperty);
}
set
{
SetValue(StateProperty, value);
if(value == MenuState.Visible)
{
Show();
}
else
{
Hide();
}
}
}
#endregion
#region 메뉴 너비 - MenuWidth
/// <summary>
/// 메뉴 너비
/// </summary>
public double MenuWidth
{
get
{
return (double)GetValue(MenuWidthProperty);
}
set
{
SetValue(MenuWidthProperty, value);
}
}
#endregion
#region 메뉴 - Menu
/// <summary>
/// 메뉴
/// </summary>
public ScrollViewer Menu
{
get
{
return (ScrollViewer)GetValue(MenuProperty);
}
set
{
SetValue(MenuProperty, value);
}
}
#endregion
#region 그림자 배경 - ShadowBackground
/// <summary>
/// 그림자 배경
/// </summary>
public Brush ShadowBackground
{
get
{
return (Brush)GetValue(ShadowBackgroundProperty);
}
set
{
SetValue(ShadowBackgroundProperty, value);
Resources["ShadowSolidColorBrushKey"] = value ?? new SolidColorBrush { Color = Colors.Black, Opacity = .2 };
}
}
#endregion
#region 버튼 배경 - ButtonBackground
/// <summary>
/// 버튼 배경
/// </summary>
public Brush ButtonBackground
{
get
{
return (Brush)GetValue(ButtonBackgroundProperty);
}
set
{
SetValue(ButtonBackgroundProperty, value);
Resources["ButtonBackgroundSolidColorBrushKey"] = value;
}
}
#endregion
#region 버튼 HOVER - ButtonHover
/// <summary>
/// 버튼 HOVER
/// </summary>
public Brush ButtonHover
{
get
{
return (Brush)GetValue(ButtonHoverProperty);
}
set
{
SetValue(ButtonHoverProperty, value);
Resources["ButtonHoverSolidColorBrushKey"] = value;
}
}
#endregion
#region 종료 타입 - ClosingType
/// <summary>
/// 종료 타입
/// </summary>
public ClosingType ClosingType { get; set; }
#endregion
#region 표시 여부 - IsShown
/// <summary>
/// 표시 여부
/// </summary>
public bool IsShown
{
get
{
return this.isShown;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - SideMenu()
/// <summary>
/// 생성자
/// </summary>
public SideMenu()
{
InitializeComponent();
Theme = SideMenuTheme.Default;
ClosingType = ClosingType.Auto;
this.shadowBorder.MouseDown += shadowBorder_MouseDown;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 템플리트 적용시 처리하기 - OnApplyTemplate()
/// <summary>
/// 템플리트 적용시 처리하기
/// </summary>
public override void OnApplyTemplate()
{
Panel.SetZIndex(this, int.MaxValue);
RenderTransform = new TranslateTransform(-MenuWidth, 0);
(FindName("menuColumnDefinition") as ColumnDefinition).Width = new GridLength(MenuWidth);
State = State;
Theme = Theme;
ShadowBackground = ShadowBackground;
ButtonBackground = ButtonBackground;
ButtonHover = ButtonHover;
}
#endregion
#region 보여주기 - Show()
/// <summary>
/// 보여주기
/// </summary>
public void Show()
{
DoubleAnimation animation = new DoubleAnimation
{
From = -MenuWidth * 0.85,
To = 0,
Duration = TimeSpan.FromMilliseconds(100)
};
RenderTransform.BeginAnimation(TranslateTransform.XProperty, animation);
this.isShown = true;
(FindName("shadowColumnDefinition") as ColumnDefinition).Width = new GridLength(10000);
}
#endregion
#region 숨기기 - Hide()
/// <summary>
/// 숨기기
/// </summary>
public void Hide()
{
DoubleAnimation animation = new DoubleAnimation
{
To = -MenuWidth,
Duration = TimeSpan.FromMilliseconds(100)
};
RenderTransform.BeginAnimation(TranslateTransform.XProperty, animation);
this.isShown = false;
(FindName("shadowColumnDefinition") as ColumnDefinition).Width = new GridLength(0);
}
#endregion
#region 토글하기 - Toggle()
/// <summary>
/// 토글하기
/// </summary>
public void Toggle()
{
if(this.isShown)
{
Hide();
}
else
{
Show();
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 그림자 테두리 마우스 DOWN 처리하기 - shadowBorder_MouseDown(sender, e)
/// <summary>
/// 그림자 테두리 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void shadowBorder_MouseDown(object sender, MouseButtonEventArgs e)
{
if(ClosingType == ClosingType.Auto)
{
Hide();
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 메뉴 버튼 배경 설정하기 - SetMenuButtonBackground(parentButton, buttonBackground, buttonHoverBackground)
/// <summary>
/// 메뉴 버튼 배경 설정하기
/// </summary>
/// <param name="parentButton">부모 버튼</param>
/// <param name="buttonBackground">버튼 배경</param>
/// <param name="buttonHoverBackground">버튼 HOVER 배경</param>
private void SetMenuButtonBackground(MenuButton parentButton, Brush buttonBackground, SolidColorBrush buttonHoverBackground)
{
parentButton.HoverBackground = buttonHoverBackground;
parentButton.SetBackground(buttonBackground);
foreach(MenuButton childButton in parentButton.Children)
{
SetMenuButtonBackground(childButton, buttonBackground, buttonHoverBackground);
}
}
#endregion
}
}
[TestProject 프로젝트]
▶ MainWindow.xaml
<Window x:Class="TestProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:library="clr-namespace:TestLibrary;assembly=TestLibrary"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Width="800"
Height="600"
Title="Material 메뉴 사용하기"
Foreground="WhiteSmoke"
FontFamily="나눔고딕코딩"
FontSize="16">
<Window.Resources>
<Style x:Key="TransparentPanelStyleKey" TargetType="Border">
<Setter Property="BorderBrush" Value="#66444444" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1">
<GradientStop Color="#bb222222" Offset="0" />
<GradientStop Color="#aa444444" Offset="0.6" />
<GradientStop Color="#99222222" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush
Stretch="UniformToFill"
ImageSource="IMAGE/mainBackground.jpg" />
</Grid.Background>
<library:SideMenu x:Name="customSideMenu"
HorizontalAlignment="Left"
MenuWidth="300"
Theme="None"
State="Hidden"
ButtonBackground="Red"
ButtonHover="Black"
ShadowBackground="Black">
<library:SideMenu.Menu>
<ScrollViewer
VerticalScrollBarVisibility="Hidden"
Background="Blue">
<StackPanel Orientation="Vertical">
<Border Background="BlueViolet">
<Grid Margin="10">
<TextBox
VerticalContentAlignment="Bottom"
Height="100"
BorderThickness="0"
Background="Transparent"
Foreground="WhiteSmoke"
FontWeight="Bold"
FontSize="18">
커스텀 색상 예제 입니다.
</TextBox>
</Grid>
</Border>
<library:MenuButton
Image="IMAGE/bossLight.png"
Text="관리" />
<library:MenuButton
Image="IMAGE/boxLight.png"
Text="포장" />
<library:MenuButton
Image="IMAGE/bugLight.png"
Text="물류" />
<library:MenuButton
Image="IMAGE/organizationLight.png"
Text="조직도" />
<library:MenuButton
Image="IMAGE/saveLight.png"
Text="변경 사항 저장" />
<library:MenuButton
Image="IMAGE/HelpLight.png"
Text="도움말" />
<library:MenuButton
Image="IMAGE/closeLight.png"
Text="메뉴 닫기" />
</StackPanel>
</ScrollViewer>
</library:SideMenu.Menu>
</library:SideMenu>
<library:SideMenu x:Name="defaultSideMenu"
HorizontalAlignment="Left"
MenuWidth="300"
Theme="Default"
State="Hidden">
<library:SideMenu.Menu>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<StackPanel Orientation="Vertical">
<Border>
<Border.Background>
<ImageBrush
Stretch="None"
AlignmentX="Right"
ImageSource="IMAGE/sideMenuBackground.jpg" />
</Border.Background>
<Grid Margin="10">
<TextBox
VerticalContentAlignment="Bottom"
Height="50"
BorderThickness="0"
Background="Transparent"
Foreground="WhiteSmoke"
FontFamily="Calibri"
FontWeight="Bold"
FontSize="18">
환영합니다!
</TextBox>
</Grid>
</Border>
<library:MenuButton Image="IMAGE/bossLight.png" Text="자료">
<library:MenuButton.Children>
<library:MenuButton Text="일반" Image="IMAGE/helpLight.png">
<library:MenuButton.Children>
<library:MenuButton Text="도서" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
<library:MenuButton Text="백과사전" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
<library:MenuButton Text="한자사전" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
<library:MenuButton Text="역사" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
</library:MenuButton.Children>
</library:MenuButton>
<library:MenuButton Text="경제" Image="IMAGE/helpLight.png">
<library:MenuButton.Children>
<library:MenuButton Text="자료실" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
</library:MenuButton.Children>
</library:MenuButton>
<library:MenuButton Text="전쟁" Image="IMAGE/helpLight.png">
<library:MenuButton.Children>
<library:MenuButton Text="전쟁사" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
<library:MenuButton Text="무기 체계" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
<library:MenuButton Text="세계 정세" Image="IMAGE/boxLight.png" MouseDown="menuButton_Click" />
</library:MenuButton.Children>
</library:MenuButton>
</library:MenuButton.Children>
</library:MenuButton>
<library:MenuButton
Image="IMAGE/closeLight.png"
Text="메뉴 닫기"
MouseDown="closeMenuButton_Click" />
</StackPanel>
</ScrollViewer>
</library:SideMenu.Menu>
</library:SideMenu>
<Border
Style="{StaticResource TransparentPanelStyleKey}"
HorizontalAlignment="Right">
<StackPanel
Margin="10"
Width="200"
Orientation="Vertical">
<Button Name="showDefaultSideMenuButton"
Margin="10">
<Button.Template>
<ControlTemplate>
<Border
HorizontalAlignment="Right"
Width="50"
Height="50"
CornerRadius="3"
BorderBrush="DarkGray"
BorderThickness="1"
Background="WhiteSmoke">
<Image
Margin="12"
Source="IMAGE/dark64.png" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Button Name="showCustomSideMenuButton"
Margin="10">
<Button.Template>
<ControlTemplate>
<Border
HorizontalAlignment="Right"
Width="50"
Height="50"
CornerRadius="3"
BorderBrush="DarkGray"
BorderThickness="1"
Background="#00b500">
<Image
Margin="12"
Source="IMAGE/dark64.png" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<StackPanel
Orientation="Vertical"
Background="Transparent">
<Button Name="defaultSideMenuThemeButton"
Margin="0 10 0 0"
Width="100"
Height="30"
Background="#303030"
Foreground="WhiteSmoke">
Default
</Button>
<Button Name="primarySideMenuThemeButton"
Margin="0 10 0 0"
Width="100"
Height="30"
Background="#337ab6"
Foreground="WhiteSmoke">
Primary
</Button>
<Button Name="successSideMenuThemeButton"
Margin="0 10 0 0"
Width="100"
Height="30"
Background="#5cb75c"
Foreground="WhiteSmoke">
Success
</Button>
<Button Name="warningSideMenuThemeButton"
Margin="0 10 0 0"
Width="100"
Height="30"
Background="#efac4e"
Foreground="WhiteSmoke">
Warning
</Button>
<Button Name="dangerSideMenuThemeButton"
Margin="0 10 0 0"
Width="100"
Height="30"
Background="#D8534F"
Foreground="WhiteSmoke">
Danger
</Button>
</StackPanel>
<StackPanel
Margin="0 20 0 0"
Background="Transparent">
<TextBlock
Foreground="White"
TextWrapping="Wrap"
FontWeight="Bold">
아래 버튼을 클릭하면 메뉴에서 닫기 버튼을 눌러야 할 때 자동/수동 닫기 유형이 변경됩니다.
</TextBlock>
<Button Name="toggleClosingTypeButton"
Margin="0 10 0 0"
Width="150"
Height="30">
종료 타입 토글
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Window>
▶ MainWindow.xaml.cs
using System.Windows;
using TestLibrary;
namespace TestProject
{
/// <summary>
/// 메인 윈도우
/// </summary>
public partial class MainWindow
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainWindow()
/// <summary>
/// 생성자
/// </summary>
public MainWindow()
{
InitializeComponent();
this.showDefaultSideMenuButton.Click += showDefaultSideMenuButton_Click;
this.showCustomSideMenuButton.Click += showCustomSideMenuButton_Click;
this.defaultSideMenuThemeButton.Click += defaultSideMenuThemeButton_Click;
this.primarySideMenuThemeButton.Click += primarySideMenuThemeButton_Click;
this.successSideMenuThemeButton.Click += successSideMenuThemeButton_Click;
this.warningSideMenuThemeButton.Click += warningSideMenuThemeButton_Click;
this.dangerSideMenuThemeButton.Click += dangerSideMenuThemeButton_Click;
this.toggleClosingTypeButton.Click += toggleClosingTypeButton_Click;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 디폴트 사이드 메뉴 표시 버튼 클릭시 처리하기 - showDefaultSideMenuButton_Click(sender, e)
/// <summary>
/// 디폴트 사이드 메뉴 표시 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void showDefaultSideMenuButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Toggle();
}
#endregion
#region 커스텀 사이드 메뉴 표시 버튼 클릭시 처리하기 - showCustomSideMenuButton_Click(sender, e)
/// <summary>
/// 커스텀 사이드 메뉴 표시 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void showCustomSideMenuButton_Click(object sender, RoutedEventArgs e)
{
this.customSideMenu.Toggle();
}
#endregion
#region DEFAULT 사이드 메뉴 테마 버튼 클릭시 처리하기 - defaultSideMenuThemeButton_Click(sender, e)
/// <summary>
/// DEFAULT 사이드 메뉴 테마 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void defaultSideMenuThemeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Theme = SideMenuTheme.Default;
}
#endregion
#region PRIMARY 사이드 메뉴 테마 버튼 클릭시 처리하기 - primarySideMenuThemeButton_Click(sender, e)
/// <summary>
/// PRIMARY 사이드 메뉴 테마 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void primarySideMenuThemeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Theme = SideMenuTheme.Primary;
}
#endregion
#region SUCCESS 사이드 메뉴 테마 버튼 클릭시 처리하기 - successSideMenuThemeButton_Click(sender, e)
/// <summary>
/// SUCCESS 사이드 메뉴 테마 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void successSideMenuThemeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Theme = SideMenuTheme.Success;
}
#endregion
#region WARNING 사이드 메뉴 테마 버튼 클릭시 처리하기 - warningSideMenuThemeButton_Click(sender, e)
/// <summary>
/// WARNING 사이드 메뉴 테마 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void warningSideMenuThemeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Theme = SideMenuTheme.Warning;
}
#endregion
#region DANGER 사이드 메뉴 테마 버튼 클릭시 처리하기 - dangerSideMenuThemeButton_Click(sender, e)
/// <summary>
/// DANGER 사이드 메뉴 테마 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void dangerSideMenuThemeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Theme = SideMenuTheme.Danger;
}
#endregion
#region 종료 타입 토글 버튼 클릭시 처리하기 - toggleClosingTypeButton_Click(sender, e)
/// <summary>
/// 종료 타입 토글 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void toggleClosingTypeButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.ClosingType = this.defaultSideMenu.ClosingType == ClosingType.Auto ? ClosingType.Manual : ClosingType.Auto;
}
#endregion
#region 메뉴 버튼 클릭시 처리하기 - menuButton_Click(sender, e)
/// <summary>
/// 메뉴 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void menuButton_Click(object sender, RoutedEventArgs e)
{
MenuButton menuButton = sender as MenuButton;
MessageBox.Show(this, $"{menuButton.Text} 메뉴를 클릭했습니다.");
}
#endregion
#region 메뉴 닫기 버튼 클릭시 처리하기 - closeMenuButton_Click(sender, e)
/// <summary>
/// 메뉴 닫기 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void closeMenuButton_Click(object sender, RoutedEventArgs e)
{
this.defaultSideMenu.Hide();
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] TextBox 클래스 : PreviewTextInput 이벤트를 사용해 3자리마다 콤마를 갖는 숫자 입력하기 (0) | 2020.09.14 |
---|---|
[C#/WPF] LogicalTreeHelper 클래스 : FindLogicalNode 정적 메소드를 사용해 엘리먼트 찾기 (0) | 2020.09.14 |
[C#/WPF] CollectionViewSource 엘리먼트 : Source 속성 사용하기 (0) | 2020.09.14 |
[C#/WPF] BindingOperations 클래스 : ClearBinding/SetBinding 정적 메소드를 사용해 바인딩하기 (0) | 2020.09.14 |
[C#/WPF] Grid 클래스 : 자동 인덱스 설정 그리드 사용하기 (0) | 2020.09.13 |
[C#/WPF] Animatable 클래스 : BeginAnimation 메소드를 사용해 공 움직이기 (0) | 2020.09.11 |
[C#/WPF] UIElement 클래스 : BeginAnimation 메소드를 사용해 애니메이션 시작하기 (0) | 2020.09.11 |
[C#/WPF] DoubleAnimation 클래스 : 사각형 높이 변경하기 (0) | 2020.09.11 |
[C#/WPF] Storyboard 클래스 : Begin/Pause/Resume/SkipToFill/SetSpeedRatio/Stop 메소드 사용하기 (0) | 2020.09.11 |
[C#/WPF] TreeView 엘리먼트 : AlternationConverter 객체를 사용해 트리 뷰 항목 배경색/폰트 스타일 설정하기 (0) | 2020.09.11 |
댓글을 달아 주세요