728x90
반응형
728x170
[TestLibrary 프로젝트]
▶ ExpandableListBoxStyle.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestLibrary">
<Style x:Key="BorderStyleKey" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="0 1" />
<Setter Property="BorderBrush" Value="#ff484848" />
<Setter Property="Background" Value="#ff525252" />
</Style>
<Style x:Key="ExpanderToggleButtonStyleKey" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Name="border"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<TextBlock Name="iconTextBlock"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="▽" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter
TargetName="border"
Property="BorderBrush"
Value="#ff363636" />
<Setter
TargetName="border"
Property="Background"
Value="#ff424343" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter
TargetName="border"
Property="BorderBrush"
Value="#ff2d2d2d" />
<Setter
TargetName="border"
Property="Background"
Value="#FF373838" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter
TargetName="iconTextBlock"
Property="Text"
Value="△" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderStyleKey" TargetType="{x:Type Expander}">
<Setter
Property="IsExpanded"
Value="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Height="35">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
Style="{StaticResource BorderStyleKey}">
<TextBlock
VerticalAlignment="Center"
Margin="22 0 0 0"
Foreground="#FFDDDDDD"
Text="{TemplateBinding Header}" />
</Border>
<ToggleButton Grid.Column="1"
Style="{DynamicResource ExpanderToggleButtonStyleKey}"
Width="28"
Height="35"
BorderThickness="1 1 0 1"
BorderBrush="#FF484848"
Background="#ff4d4e4e"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
</Grid>
<ContentPresenter Name="ExpandSite" Grid.Row="1"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
Focusable="false"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter
TargetName="ExpandSite"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxItemStyleKey" TargetType="{x:Type ListBoxItem}">
<Setter
Property="HorizontalContentAlignment"
Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter
Property="VerticalContentAlignment"
Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Expander
Style="{StaticResource ExpanderStyleKey}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Header="{Binding Header}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:ExpandableListBox}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter
Property="ItemContainerStyle"
Value="{StaticResource ListBoxItemStyleKey}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
Focusable="false">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
728x90
▶ ExpandableListBox.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace TestLibrary
{
/// <summary>
/// 확장 가능한 리스트 박스
/// </summary>
public class ExpandableListBox : ListBox
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Static
#region 생성자 - ExpandableListBox()
/// <summary>
/// 생성자
/// </summary>
static ExpandableListBox()
{
DefaultStyleKeyProperty.OverrideMetadata
(
typeof(ExpandableListBox),
new FrameworkPropertyMetadata(typeof(ExpandableListBox))
);
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 초기화시 처리하기 - OnInitialized(e)
/// <summary>
/// 초기화시 처리하기
/// </summary>
/// <param name="e">이벤트 인자</param>
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 항목 컨테이너 제너레이터 상태 변경시 처리하기 - ItemContainerGenerator_StatusChanged(sender, e)
/// <summary>
/// 항목 컨테이너 제너레이터 상태 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
try
{
double actualHeight = ActualHeight;
if(ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
IEnumerable<object> itemEnumerable = Items.OfType<object>();
ListBoxItem firstOfvalidListBoxItems =
(
from item in itemEnumerable
let listBoxItem = ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem
where listBoxItem.IsSelected == false && listBoxItem.ActualHeight != 0
select listBoxItem
).FirstOrDefault();
if(firstOfvalidListBoxItems == null)
{
return;
}
double collapsedHeight = firstOfvalidListBoxItems.ActualHeight * Items.Count;
foreach(object item in itemEnumerable)
{
ListBoxItem listBoxItem = ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
Expander expander = VisualTreeHelper.GetChild(listBoxItem, 0) as Expander;
if(expander == null)
{
break;
}
FrameworkElement element = expander.Content as FrameworkElement;
if(element == null)
{
break;
}
double elementHeight = (actualHeight - collapsedHeight);
if(elementHeight >= 0)
{
element.Height = elementHeight;
}
}
}
}
catch(Exception exception)
{
Debug.WriteLine(exception);
}
}
#endregion
}
}
300x250
[TestProject 프로젝트]
▶ MenuItem.cs
using System.Windows;
namespace TestProject
{
/// <summary>
/// 메뉴 항목
/// </summary>
public class MenuItem : DependencyObject
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 헤더 속성 - HeaderProperty
/// <summary>
/// 헤더 속성
/// </summary>
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register
(
"Header",
typeof(object),
typeof(MenuItem),
new PropertyMetadata(null)
);
#endregion
#region 컨텐트 속성 - ContentProperty
/// <summary>
/// 컨텐트 속성
/// </summary>
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register
(
"Content",
typeof(object),
typeof(MenuItem),
new PropertyMetadata(null)
);
#endregion
#region 확장 여부 속성 - IsExpandedProperty
/// <summary>
/// 확장 여부 속성
/// </summary>
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register
(
"IsExpanded",
typeof(bool),
typeof(MenuItem),
new PropertyMetadata(false)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 헤더 - Header
/// <summary>
/// 헤더
/// </summary>
public object Header
{
get
{
return (object)GetValue(HeaderProperty);
}
set
{
SetValue(HeaderProperty, value);
}
}
#endregion
#region 컨텐트 - Content
/// <summary>
/// 컨텐트
/// </summary>
public object Content
{
get
{
return (object)GetValue(ContentProperty);
}
set
{
SetValue(ContentProperty, value);
}
}
#endregion
#region 확장 여부 - IsExpanded
/// <summary>
/// 확장 여부
/// </summary>
public bool IsExpanded
{
get
{
return (bool)GetValue(IsExpandedProperty);
}
set
{
SetValue(IsExpandedProperty, value);
}
}
#endregion
}
}
▶ 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:local="clr-namespace:TestLibrary;assembly=TestLibrary"
Width="800"
Height="600"
Title="ListBox 클래스 : 확장 가능한 리스트 박스 사용하기"
FontFamily="나눔고딕코딩"
FontSize="16">
<DockPanel LastChildFill="False">
<local:ExpandableListBox x:Name="expandableListBox" DockPanel.Dock="Left"
Width="300"
Background="Gray">
<local:ExpandableListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<TextBlock Text="{Binding Content}" />
</StackPanel>
</DataTemplate>
</local:ExpandableListBox.ItemTemplate>
</local:ExpandableListBox>
</DockPanel>
</Window>
▶ MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.Windows;
namespace TestProject
{
/// <summary>
/// 메인 윈도우
/// </summary>
public partial class MainWindow : Window
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainWindow()
/// <summary>
/// 생성자
/// </summary>
public MainWindow()
{
InitializeComponent();
ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
collection.Add(new MenuItem { Header = "메일" , Content = "메일 컨텐트" });
collection.Add(new MenuItem { Header = "달력" , Content = "달력 컨텐트" });
collection.Add(new MenuItem { Header = "연락처", Content = "연락처 컨텐트" });
collection.Add(new MenuItem { Header = "일정표", Content = "일정표 컨텐트" });
this.expandableListBox.ItemsSource = collection;
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] Shape 클래스 : 커스텀 파일 슬라이스(Pie Slice) 사용하기 (0) | 2021.02.14 |
---|---|
[C#/WPF] BitmapSource 클래스 : WINFORM Bitmap 객체 구하기 (0) | 2021.02.14 |
[C#/WPF] RenderTargetBitmap 클래스 : Image 객체에서 비트맵 구하기 (0) | 2021.02.14 |
[C#/WPF] MultiSelector 클래스 : 선택/이동/크기 변경 가능한 캔버스 사용하기 (0) | 2021.02.13 |
[C#/WPF] Canvas 클래스 : 자식 엘리먼트 드래그하기 (0) | 2021.02.13 |
[C#/WPF] ListBox 클래스 : 확장 가능한 리스트 박스 사용하기 (0) | 2021.02.12 |
[C#/WPF] 누겟 설치 : System.Windows.Interactivity.WPF (0) | 2021.02.12 |
[C#/WPF] 디자인 타임에서 리소스 딕셔너리 로드하기 (0) | 2021.02.12 |
[C#/WPF] 리소스 병합 설정하기 (0) | 2021.02.12 |
[C#/WPF] 리소스 병합하기 (0) | 2021.02.12 |
[C#/WPF] 애니메이션 메시지 컨트롤 사용하기 (0) | 2021.02.11 |
댓글을 달아 주세요