티스토리 뷰
반응형
리플로 문의 주신 내용이 있어서 추가 작업을 진행했습니다.
빈공간이나 OK를 클릭하면 팝업이 닫히도록 수정했습니다.
1. MainViewModel.cs
이 작업의 핵심은 CloseLayerPopupCommand를 호출하고, 클릭한 위치가 빈공간인지 확인해서 빈공간일 때만 닫아주는 것입니다.
- public ICommand CloseLayerPopupCommand { get; set; }
- 커맨드를 추가합니다.
- CloseLayerPopupCommand = new RelayCommand<object>(OnCloseLayerPopup);
- 커맨드를 생성할 때 CommandParameter를 받을 수 있도록 만들어 줍니다.
- OnCloseLayerPopup 메서드
- f (sender is not MouseButtonEventArgs args
|| args.OriginalSource is not Border border
|| border.Name != "LayerPopupBorder")- 이벤트 발생시 생성된 EventArgs를 분석해서, LayerPopupBorder라는 이름의 border에서 발생한 이벤트가 아니면 무시합니다.
- OnLayerPopupMessage(null, new LayerPopupMessage(false));
- 레이어 팝업을 닫기 위해서 호출합니다.
- f (sender is not MouseButtonEventArgs args
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using WpfFramework.Bases;
using WpfFramework.Models;
namespace WpfFramework.ViewModels
{
/// <summary>
/// 메인 뷰모델 클래스
/// </summary>
public class MainViewModel : ViewModelBase
{
/// <summary>
/// Busy 목록
/// </summary>
private readonly IList<BusyMessage> _busys = new List<BusyMessage>();
private string _navigationSource;
/// <summary>
/// 네비게이션 소스
/// </summary>
public string NavigationSource
{
get => _navigationSource;
set => SetProperty(ref _navigationSource, value);
}
/// <summary>
/// 네비게이트 커맨드
/// </summary>
public ICommand NavigateCommand { get; set; }
private bool _isBusy;
/// <summary>
/// IsBusy
/// </summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private bool _showLayerPopup;
/// <summary>
/// 레이어 팝업 출력여부
/// </summary>
public bool ShowLayerPopup
{
get => _showLayerPopup;
set => SetProperty(ref _showLayerPopup, value);
}
private string _controlName;
/// <summary>
/// 레이어 팝업 내부 컨트롤 이름
/// </summary>
public string ControlName
{
get => _controlName;
set => SetProperty(ref _controlName, value);
}
private object _controlParameter;
/// <summary>
/// 컨트롤 파라메터
/// </summary>
public object ControlParameter
{
get => _controlParameter;
set => SetProperty(ref _controlParameter, value);
}
/// <summary>
/// 레이어 팝업 닫기 커맨드
/// </summary>
public ICommand CloseLayerPopupCommand { get; set; }
/// <summary>
/// 생성자
/// </summary>
public MainViewModel()
{
Title = "Main View";
Init();
}
private void Init()
{
//시작 페이지 설정
NavigationSource = "Views/LoginPage.xaml";
NavigateCommand = new RelayCommand<string>(OnNavigate);
CloseLayerPopupCommand = new RelayCommand<object>(OnCloseLayerPopup);
//네비게이션 메시지 수신 등록
WeakReferenceMessenger.Default.Register<NavigationMessage>(this, OnNavigationMessage);
//BusyMessage 수신 등록
WeakReferenceMessenger.Default.Register<BusyMessage>(this, OnBusyMessage);
//LayerPopupMessage 수신 등록
WeakReferenceMessenger.Default.Register<LayerPopupMessage>(this, OnLayerPopupMessage);
}
/// <summary>
/// 레이어 팝업 닫기
/// </summary>
private void OnCloseLayerPopup(object sender)
{
//sender는 마우스 다운 이벤트 아규먼트가 들어오고, 클릭한 위치가 보더가 아니거나
//보더의 이름이 지정한 이름과 다르면 닫지 않음
if (sender is not MouseButtonEventArgs args
|| args.OriginalSource is not Border border
|| border.Name != "LayerPopupBorder")
{
return;
}
OnLayerPopupMessage(null, new LayerPopupMessage(false));
}
private void OnLayerPopupMessage(object recipient, LayerPopupMessage message)
{
ShowLayerPopup = message.Value;
//순서에 주의
ControlParameter = message.Parameter;
ControlName = message.ControlName;
}
/// <summary>
/// 비지 메시지 수신 처리
/// </summary>
/// <param name="recipient"></param>
/// <param name="message"></param>
private void OnBusyMessage(object recipient, BusyMessage message)
{
if (message.Value)
{
BusyMessage existBusy = _busys.FirstOrDefault(b => b.BusyId == message.BusyId);
if (existBusy != null)
{
//이미 추가된 녀석이기 때문에 추가하지 않음
return;
}
_busys.Add(message);
}
else
{
BusyMessage existBusy = _busys.FirstOrDefault(b => b.BusyId == message.BusyId);
if (existBusy == null)
{
//없기 때문에 나감
return;
}
_ = _busys.Remove(existBusy);
}
//_busys에 아이템이 있으면 true, 없으면 false
IsBusy = _busys.Any();
}
/// <summary>
/// 네비게이션 메시지 수신 처리
/// </summary>
/// <param name="recipient"></param>
/// <param name="message"></param>
private void OnNavigationMessage(object recipient, NavigationMessage message)
{
NavigationSource = message.Value;
}
private void OnNavigate(string pageUri)
{
NavigationSource = pageUri;
}
}
}
2. MainWindow.xaml
CloseLayerPopupCommand는 Border에 EventTrigger를 추가하고, MouseLeftButtonDown 이벤트가 발생했을 때 실행합니다.
- <b:InvokeCommandAction Command="{Binding CloseLayerPopupCommand}" PassEventArgsToCommand="True" />
- InvokeCommandAction에는 이벤트의 아규먼트를 CommandParameter로 전달하도록 해주는 프로퍼티가 있습니다. 그 프로퍼티를 True로 설정하면 됩니다.
여기까지 진행하면 딤처리된 보더를 클릭하면 커맨드가 실행되는 것을 확인 할 수 있습니다.
<!-- 클릭한 위치가 LayerPopupBorder인 경우에만 닫기 위해서 이름 추가 -->
<Border
x:Name="LayerPopupBorder"
Background="#66000000"
Visibility="{Binding ShowLayerPopup, Converter={StaticResource BoolToVisibilityConverter}}">
<b:Interaction.Triggers>
<!-- 보더에 마우스 다운 이벤트를 트리거로 걸어서 커맨드 실행 -->
<b:EventTrigger EventName="MouseLeftButtonDown">
<!-- MouseLeftButtonDown 이벤트가 발생할 때 생성된 아규먼트를 CommandParameter로 전달 -->
<b:InvokeCommandAction Command="{Binding CloseLayerPopupCommand}" PassEventArgsToCommand="True" />
</b:EventTrigger>
</b:Interaction.Triggers>
<Border
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="White"
CornerRadius="5">
<Border.Effect>
<DropShadowEffect />
</Border.Effect>
<ContentControl Width="400" MinHeight="200">
<b:Interaction.Behaviors>
<behaviors:ContentControlBehavior
ControlName="{Binding ControlName}"
ControlParameter="{Binding ControlParameter}"
ShowLayerPopup="{Binding ShowLayerPopup}" />
</b:Interaction.Behaviors>
</ContentControl>
</Border>
</Border>
3. AboutControl.xaml
그런데 여기서 문제가 기존에 팝업 출력시 사용했던 컨트롤의 Background 컬러가 지정되어 있지 않으면, 팝업에서 클릭시에도 팝업 닫기 커맨드가 실행이 된다는 점입니다.
이 문제는 Grid의 Background 컬러를 지정하는 것으로 간단하게 해결할 수 있습니다.
4. 소스
kaki104/WpfFramework at part11/edit-close-layerpopup (github.com)
반응형
'WPF .NET' 카테고리의 다른 글
ViewModel을 싱글톤으로 만들어서 계속 사용하기 (1) | 2024.01.30 |
---|---|
Kiosk 만들기 - Part9 (0) | 2023.11.07 |
Kiosk 만들기 - Part8 (2) | 2023.11.01 |
Kiosk 만들기 - Part7 (0) | 2023.10.30 |
Kiosk 만들기 - Part6 (0) | 2023.10.27 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- WPF
- .net 5.0
- #prism
- LINQ
- windows 11
- Build 2016
- C#
- Always Encrypted
- ef core
- .net
- MVVM
- uno-platform
- Microsoft
- Windows 10
- #uwp
- uno platform
- Cross-platform
- Behavior
- XAML
- PRISM
- UWP
- Visual Studio 2022
- #MVVM
- dotNETconf
- ComboBox
- #Windows Template Studio
- kiosk
- Bot Framework
- IOT
- visual studio 2019
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함