티스토리 뷰

반응형

다양한 팝업에 Paramter를 전달하는 방법에 대해서 문의 요청을 주셔서 기능을 추가해 보았습니다.

1. 배경

기존에 구현했던 팝업은 사실 보기에만 팝업이지 컨트롤을 숨겼다가, 보였다가하는 정도의 기능만 가지고 있습니다.

그래서, 파라메터를 전달하는 방법도 아마 생각하셨던 방법이 아닐 수 있습니다.

 

제대로된 Popup을 만들고, 파라메터를 전달하기 위해서는 Prism을 이용해서 IDialogService를 이용하는 것을 추천합니다. ToolKit.Mvvm 자체적으로 그런 기능을 제공하지는 않습니다.

2. ISupportParameter

파라메터를 전달하려는 컨트롤에 ISupportParameter 인터페이스를 만들어서 추가하고, 해당 인터페이스를 통해서 Parameter를 전달합니다.

 

생성자를 통해서 전달하는 방법은 사용 할 수 없습니다.

Resolve를 할 때 Parameter를 넘겨서 같이 Resolve를 할 수 있어야하는데..GetService에서는 지원을 하지않고, 다른 방법을 이용해야하는데....

 

ISupportParameter

/// <summary>
/// 컨트롤에 Parameter를 전달하기 위한 인터페이스
/// </summary>
public interface ISupportParameter
{
    /// <summary>
    /// 파라메터
    /// </summary>
    object Parameter { get; set; }
}

AboutControl.xaml.cs

인터페이스를 추가하고, Parameter라는 DP(DependencyProperty)를 추가했습니다.

컨트롤 비하인드에서는 INotifyPropertyChanged 이벤트를 발생시키는 코드가 없기 때문에, DP를 이용합니다.

만약, INotifyPropertyChanged를 이용하고 싶다면, 간단한 코드를 직접 구현 해야합니다.
/// <summary>
/// Interaction logic for AboutControl.xaml
/// </summary>
public partial class AboutControl : UserControl, ISupportParameter
{
    public AboutControl()
    {
        InitializeComponent();
    }
    public object Parameter
    {
        get { return (object)GetValue(ParameterProperty); }
        set { SetValue(ParameterProperty, value); }
    }
    /// <summary>
    /// 파라메터 - DependencyProperty이기 때문에 직접 바인딩을 하거나, Changed 이벤트를 이용해서 작업을 진행할 수 있습니다.
    /// </summary>
    public static readonly DependencyProperty ParameterProperty =
        DependencyProperty.Register(nameof(Parameter), typeof(object), typeof(AboutControl), new PropertyMetadata(null, ParameterChanged));

    private static void ParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = (AboutControl)d;
        control.OnParameterChanged();
    }

    private void OnParameterChanged()
    {
        //작업 내용 처리
    }

    /// <summary>
    /// 버튼 클릭 이벤트
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        WeakReferenceMessenger.Default.Send(new LayerPopupMessage(false));
    }
}

AboutControl.xaml

2개의 TextBlock을 추가합니다.

AbountControl의 Paramter를 바인딩으로 사용하기 위해서는 아래의 방법을 사용하거나, ElementName을 지정하는 방법을 사용할 수 있습니다.

ControlTemplate에서 사용하려면, RelativeSource Mode=TemplatedParent 를 이용할 수 있습니다.

<TextBlock Text="Parameter" />
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=local:AboutControl}, Path=Parameter}" />

3. LayerPopupMessage

팝업 메시지 발생시 Parameter에 값을 넣어서 전달합니다.

HomeViewModel.cs

private void OnLayerPopupTest()
{
    WeakReferenceMessenger.Default.Send(new LayerPopupMessage(true)
    { 
        ControlName = "AboutControl",
        Parameter = "kaki104 parameter"
    });
}

수신 후에 바인딩되어있는 프로퍼티에 값을 넣어서 ContentControlBehavior에 전달 합니다.

ControlName을 입력하기전에 Parameter를 먼저 입력해야 합니다.

MainViewModel.cs

private void OnLayerPopupMessage(object recipient, LayerPopupMessage message)
{
    ShowLayerPopup = message.Value;
    //순서에 주의
    ControlParameter = message.Parameter;
    ControlName = message.ControlName;
}

Resolve를 시킨 후 Paremeter에 값을 입력 합니다.

ContentControlBehavior.cs

/// <summary>
/// ControlName을 이용해서 컨트롤 인스턴스 시켜서 사용
/// </summary>
private void ResolveControl()
{
    if (string.IsNullOrEmpty(ControlName))
    {
        AssociatedObject.Content = null;
    }
    else
    {
        //GetType을 이용하기 위해서 AssemblyQualifiedName이 필요합니다.
        //예) typeof(AboutControl).AssemblyQualifiedName
        //다른 클래스라이브러리에 있는 컨트롤도 이름만 알면 만들 수 있습니다.
        Type type = Type.GetType($"WpfFramework.Controls.{ControlName}, WpfFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
        if (type == null)
        {
            return;
        }
        object control = App.Current.Services.GetService(type);
        //생성된 컨트롤에 파라메터 프로퍼티에 값 입력
        if(control is ISupportParameter parameterControl)
        {
            parameterControl.Parameter = ControlParameter;
        }
        AssociatedObject.Content = control;
    }
}

4. 소스

kaki104/WpfFramework at part9/add-parameter-popup (github.com)

 

GitHub - kaki104/WpfFramework

Contribute to kaki104/WpfFramework development by creating an account on GitHub.

github.com

 

반응형
댓글