728x90
반응형
728x170
▶ CustomFocusScope.cs
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace TestProject
{
/// <summary>
/// 커스텀 포커스 범위
/// </summary>
public static class CustomFocusScope
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 커스텀 포커스 스코프 여부 첨부 속성 - IsCustomFocusScopeProperty
/// <summary>
/// 커스텀 포커스 스코프 여부 첨부 속성
/// </summary>
public static readonly DependencyProperty IsCustomFocusScopeProperty = DependencyProperty.RegisterAttached
(
"IsCustomFocusScope",
typeof(bool),
typeof(CustomFocusScope),
new UIPropertyMetadata(false, IsCustomFocusScopePropertyChangedCallback)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 커스텀 포커스 범위 여부 구하기 - GetIsCustomFocusScope(element)
/// <summary>
/// 커스텀 포커스 범위 여부 구하기
/// </summary>
/// <param name="element">엘리먼트</param>
/// <returns>커스텀 포커스 범위 여부</returns>
public static bool GetIsCustomFocusScope(UIElement element)
{
return (bool)element.GetValue(IsCustomFocusScopeProperty);
}
#endregion
#region 커스텀 포커스 범위 여부 설정하기 - SetIsCustomFocusScope(element, value)
/// <summary>
/// 커스텀 포커스 범위 여부 설정하기
/// </summary>
/// <param name="element">엘리먼트</param>
/// <param name="value">커스텀 포커스 범위 여부</param>
public static void SetIsCustomFocusScope(UIElement element, bool value)
{
element.SetValue(IsCustomFocusScopeProperty, value);
}
#endregion
#region 범위 내에서 활성 엘리먼트 포커스 설정하기 - SetFocusOnActiveElementInScope(focusScopeElement)
/// <summary>
/// 범위 내에서 활성 엘리먼트 포커스 설정하기
/// </summary>
/// <param name="focusScopeElement">포커스 범위 엘리먼트</param>
public static void SetFocusOnActiveElementInScope(UIElement focusScopeElement)
{
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScopeElement);
if(focusedElement != null)
{
Keyboard.Focus(focusedElement);
}
else
{
focusScopeElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 커스텀 포커스 범위 여부 속성 변경시 콜백 처리하기 - IsCustomFocusScopePropertyChangedCallback(d, e)
/// <summary>
/// 커스텀 포커스 범위 여부 속성 변경시 콜백 처리하기
/// </summary>
/// <param name="d">의존 객체</param>
/// <param name="e">이벤트 인자</param>
private static void IsCustomFocusScopePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UIElement element = d as UIElement;
if(element == null)
{
return;
}
if((bool)e.NewValue)
{
FocusManager.SetIsFocusScope(element, true);
element.GotKeyboardFocus += element_GotKeyboardFocus;
}
else
{
FocusManager.SetIsFocusScope(element, false);
element.GotKeyboardFocus -= element_GotKeyboardFocus;
}
}
#endregion
#region 엘리먼트 키보드 포커스 획득시 처리하기 - element_GotKeyboardFocus(sender, e)
/// <summary>
/// 엘리먼트 키보드 포커스 획득시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private static void element_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
IInputElement focusedElement = e.NewFocus;
for(DependencyObject d = focusedElement as DependencyObject; d != null; d = VisualTreeHelper.GetParent(d))
{
if(FocusManager.GetIsFocusScope(d))
{
d.SetValue(FocusManager.FocusedElementProperty, focusedElement);
if(!(bool)d.GetValue(IsCustomFocusScopeProperty))
{
break;
}
}
}
}
#endregion
}
}
728x90
▶ 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:TestProject"
Width="800"
Height="600"
Title="커스텀 포커스 범위 사용하기"
FontFamily="나눔고딕코딩"
FontSize="16">
<Window.Resources>
<Style TargetType="GroupBox">
<Setter Property="Background" Value="Transparent" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="Cycle" />
<Setter Property="KeyboardNavigation.ControlTabNavigation" Value="Once" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="150" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToolBar Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
<Button
Margin="10 0 0 0"
Command="Copy">
복사
</Button>
<Button
Margin="10 0 0 0"
Command="Cut">
잘라내기
</Button>
<Button
Margin="10 0 0 0"
Command="Paste">
붙여넣기
</Button>
</ToolBar>
<TextBox Grid.Row="1" Grid.ColumnSpan="3"
Margin="10"
BorderThickness="1"
BorderBrush="Black"
Padding="10"
AcceptsReturn="True">
A free text area
</TextBox>
<GroupBox Name="groupBox1" Grid.Row="2" Grid.Column="0"
Header="포커스 범위 없음">
<StackPanel Margin="10">
<Button Height="30">A</Button>
<Button Height="30">B</Button>
<Button Height="30">C</Button>
<TextBox
Margin="0 10 0 0"
Height="25"
VerticalContentAlignment="Center" />
<CheckBox Margin="0 10 0 0">CheckBox</CheckBox>
</StackPanel>
</GroupBox>
<GroupBox Name="groupBox2" Grid.Row="2" Grid.Column="1"
Header="WPF 포커스 범위"
FocusManager.IsFocusScope="True">
<StackPanel Margin="10">
<Button Height="30">A</Button>
<Button Height="30">B</Button>
<Button Height="30">C</Button>
<TextBox
Margin="0 10 0 0"
Height="25"
VerticalContentAlignment="Center" />
<CheckBox Margin="0 10 0 0">CheckBox</CheckBox>
</StackPanel>
</GroupBox>
<GroupBox Name="groupBox3" Grid.Row="2" Grid.Column="2"
Header="커스텀 포커스 범위"
local:CustomFocusScope.IsCustomFocusScope="True">
<StackPanel Margin="10">
<Button Height="30">A</Button>
<Button Height="30">B</Button>
<Button Height="30">C</Button>
<TextBox
Margin="0 10 0 0"
Height="25"
VerticalContentAlignment="Center" />
<CheckBox Margin="0 10 0 0">CheckBox</CheckBox>
</StackPanel>
</GroupBox>
</Grid>
</Window>
반응형
▶ MainWindow.xaml.cs
using System.Reflection;
using System.Windows;
using System.Windows.Input;
namespace TestProject
{
/// <summary>
/// 메인 윈도우
/// </summary>
public partial class MainWindow : Window
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainWindow()
/// <summary>
/// 생성자
/// </summary>
public MainWindow()
{
InitializeComponent();
this.groupBox1.MouseDown += groupBox1_MouseDown;
this.groupBox2.MouseDown += groupBox2_MouseDown;
this.groupBox3.MouseDown += groupBox3_MouseDown;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 그룹 박스 1 마우스 DOWN 처리하기 - groupBox1_MouseDown(sender, e)
/// <summary>
/// 그룹 박스 1 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void groupBox1_MouseDown(object sender, MouseButtonEventArgs e)
{
object keyboardNavigation = typeof(KeyboardNavigation).InvokeMember
(
"Current",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty,
null,
null,
null
);
object activeElement = typeof(KeyboardNavigation).InvokeMember
(
"GetActiveElement",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
null,
keyboardNavigation,
new object[] { this.groupBox1 }
);
IInputElement focusedElement = activeElement as IInputElement;
if(focusedElement != null)
{
Keyboard.Focus(focusedElement);
}
else
{
this.groupBox1.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
#endregion
#region 그룹 박스 2 마우스 DOWN 처리하기 - groupBox2_MouseDown(sender, e)
/// <summary>
/// 그룹 박스 2 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void groupBox2_MouseDown(object sender, MouseButtonEventArgs e)
{
IInputElement focusedElement = FocusManager.GetFocusedElement(this.groupBox2);
if(focusedElement != null)
{
Keyboard.Focus(focusedElement);
}
else
{
this.groupBox2.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
#endregion
#region 그룹 박스 3 마우스 DOWN 처리하기 - groupBox3_MouseDown(sender, e)
/// <summary>
/// 그룹 박스 3 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void groupBox3_MouseDown(object sender, MouseButtonEventArgs e)
{
CustomFocusScope.SetFocusOnActiveElementInScope(this.groupBox3);
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] WeakEventManager<TEventSource, TEventArgs> 클래스 : AddHandler 정적 메소드를 사용해 이벤트 핸들러 추가하기 (0) | 2022.01.28 |
---|---|
[C#/WPF] EventManager 클래스 : RegisterClassHandler 정적 메소드를 사용해 특정 라우팅 이벤트에 대한 클래스 처리기 등록하기 (0) | 2022.01.27 |
[C#/WPF] ControlTemplate 엘리먼트 : Button 엘리먼트 정의하기 (0) | 2022.01.27 |
[C#/WPF] Decorator 엘리먼트 : 커스텀 버튼 크롬 만들기 (0) | 2022.01.27 |
[C#/WPF] ButtonChrome 엘리먼트 사용하기 (0) | 2022.01.27 |
[C#/WPF] Image 클래스 : 이미지 색상 선택기 사용하기 (0) | 2022.01.22 |
[C#/WPF] IValueConverter 인터페이스 : 색상→단색 브러시 변환자 사용하기 (0) | 2022.01.22 |
[C#/WPF] FrameworkElement 클래스 : ContextMenuOpening 이벤트를 사용해 컨텍스트 메뉴 표시 방지하기 (0) | 2022.01.19 |
[C#/WPF] FrameworkElement 클래스 : ContextMenuOpening 이벤트를 사용해 전체 컨텍스트 메뉴 항목 교체하기 (0) | 2022.01.19 |
[C#/WPF] FrameworkElement 클래스 : ContextMenuOpening 이벤트를 사용해 컨텍스트 메뉴 항목 추가하기 (0) | 2022.01.19 |
댓글을 달아 주세요