programing

MVVM을 사용하여 "창 닫기" 명령 구현

batch 2023. 5. 1. 20:39
반응형

MVVM을 사용하여 "창 닫기" 명령 구현

그래서 저의 첫 번째 시도는 뒤에 있는 코드에서 모든 것을 했고, 이제 저는 상자 정보에 있는 MVVM의 지침에 따라 MVVM 패턴을 사용하기 위해 제 코드를 리팩터링하려고 합니다.

내 뷰 클래스와 일치하도록 뷰 모델 클래스를 만들고 코드 뒤에 있는 코드를 명령부터 뷰 모델로 이동합니다.

제 첫 번째 난관은 데이터가 수정되지 않은 경우 창을 닫는 '닫기' 버튼을 구현하는 것입니다.'onClick' 메서드를 대체하기 위해 CloseCommand를 설정했는데 코드가 실행되는 곳을 제외하고는 모두 정상입니다.this.Close()분명히 코드가 창에서 일반 클래스로 이동되었기 때문에 '이것'은 창이 아니므로 닫을 수 없습니다.하지만 MVVM에 따르면 뷰 모델이 뷰를 몰라서 전화를 할 수 없습니다.view.Close().

누가 viewmodel 명령에서 창을 닫는 방법을 제안할 수 있습니까?

개인적으로 매우 간단한 접근 방식을 사용합니다. 닫기 가능한 뷰와 관련된 모든 뷰 모델에 대해 다음과 같은 기본 뷰 모델을 만들었습니다.

public abstract class CloseableViewModel
{
    public event EventHandler ClosingRequest;

    protected void OnClosingRequest()
    {
        if (this.ClosingRequest != null)
        {
            this.ClosingRequest(this, EventArgs.Empty);
        }
    }
}

그런 다음 다음 다음을 상속하는 View 모델에서CloseableViewModel간단히 말하면this.OnClosingRequest();를 위해Close지휘권

보기에서:

public class YourView
{
    ...
    var vm = new ClosableViewModel();
    this.Datacontext = vm;
    vm.ClosingRequest += (sender, e) => this.Close();
}

View 인스턴스를 View Model 도면층으로 전달할 필요는 없습니다.다음과 같이 메인 창에 액세스할 수 있습니다.

Application.Current.MainWindow.Close()

위에서 설명한 대로 ViewModel 클래스의 기본 창에 액세스하는 데 문제가 없습니다.MVVM 원칙에 따라 View와 View 모델 사이에 긴밀한 결합이 있어서는 안 됩니다. 즉, 다른 작동 방식을 무시하고 작동해야 합니다.여기서는 View에서 View Model로 전달하는 것이 없습니다.다른 옵션을 찾으려면 MVVM을 사용하여 창 닫기

단추를 클릭하는 동안 보기 모델에서 창을 닫는 방법은 다음과 같습니다.

뷰 모형

public RelayCommand CloseWindow;
Constructor()
{
    CloseWindow = new RelayCommand(CloseWin);
}

public void CloseWin(object obj)
{
    Window win = obj as Window;
    win.Close();
}

보기에서 다음과 같이 설정합니다.

<Button Command="{Binding CloseWindowCommand}" CommandParameter="{Binding ElementName=WindowNameTobeClose}" Content="Cancel" />

DialogResult:라는 첨부 속성을 생성하여 이 작업을 수행합니다.

public static class DialogCloser
{
    public static readonly DependencyProperty DialogResultProperty =
        DependencyProperty.RegisterAttached(
            "DialogResult",
            typeof(bool?),
            typeof(DialogCloser),
            new PropertyMetadata(DialogResultChanged));

    private static void DialogResultChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        var window = d as Window;
        if (window != null && (bool?)e.NewValue == true) 
                window.Close();
    }

    public static void SetDialogResult(Window target, bool? value)
    {
        target.SetValue(DialogResultProperty, value);
    }
}

그러면 이것을 창 태그에 XAML에 적습니다.

WindowActions:DialogCloser.DialogResult="{Binding Close}"

마지막으로 View 모델에서

    private bool _close;
    public bool Close
    {
        get { return _close; }
        set
        {
            if (_close == value)
                return;
            _close = value;
            NotifyPropertyChanged("Close");
        }
    }

Close를 True로 변경하면 창이 닫힙니다.

Close = True;

가장 단순하고 순수한 MVVM 솔루션은 다음과 같습니다.

모델 코드 보기

public class ViewModel
{
    public Action CloseAction { get; set; }

    private void CloseCommandFunction()
    {
        CloseAction();
    }
}

다음은 XAML 보기 코드입니다.

public partial class DialogWindow : Window
{
    public DialogWindow()
    {
        ViewModel vm = new ViewModel();
        this.DataContext = vm;

        vm.CloseAction = Close;
    }
}

이 솔루션은 빠르고 쉽습니다.단점은 레이어 간에 커플링이 있다는 것입니다.

뷰 모델에서:

public class MyWindowViewModel: ViewModelBase
{


    public Command.StandardCommand CloseCommand
    {
        get
        {
            return new Command.StandardCommand(Close);
        }
    }
    public void Close()
    {
        foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
        {
            if (window.DataContext == this)
            {
                window.Close();
            }
        }
    }
}

모든 알림 메시지를 처리하는 창을 피하기 위한 사용자 지정 메시지 알림이 포함된 MVVM-light

뷰 모델에서:

public class CloseDialogMessage : NotificationMessage
{
    public CloseDialogMessage(object sender) : base(sender, "") { }
}

private void OnClose()
{
    Messenger.Default.Send(new CloseDialogMessage(this));
}

창 생성자에 메시지를 등록합니다.

Messenger.Default.Register<CloseDialogMessage>(this, nm =>
{
    Close();
});

이것은 Eoldre의 대답과 매우 유사합니다.보기 모델이 데이터 컨텍스트와 동일한 창을 찾기 위해 동일한 Windows 컬렉션을 검색한다는 점에서 기능적으로 동일하지만, 릴레이 명령과 일부 LINQ를 사용하여 동일한 결과를 얻었습니다.

public RelayCommand CloseCommand
{
    get
    {
        return new RelayCommand(() => Application.Current.Windows
            .Cast<Window>()
            .Single(w => w.DataContext == this)
            .Close());
    }
}

MVVM-light 툴킷 사용:

뷰 모델에서:

 public void notifyWindowToClose()
{
    Messenger.Default.Send<NotificationMessage>(
        new NotificationMessage(this, "CloseWindowsBoundToMe")
    );
}

보기에서:

 Messenger.Default.Register<NotificationMessage>(this, (nm) =>
{
    if (nm.Notification == "CloseWindowsBoundToMe")
    {
        if (nm.Sender == this.DataContext)
            this.Close();
    }
});

답변으로, 이은ken2k답(감사니다합변!)을 입니다.에서 가져온 것입니다, 단지 추가합니다.CloseCommand 기에도지에도.CloseableViewModel.

public class CloseableViewModel
{
    public CloseableViewModel()
    {
        CloseCommand = new RelayCommand(this.OnClosingRequest);
    }

    public event EventHandler ClosingRequest;

    protected void OnClosingRequest()
    {
        if (this.ClosingRequest != null)
        {
            this.ClosingRequest(this, EventArgs.Empty);
        }
    }

    public RelayCommand CloseCommand
    {
        get;
        private set;
    }
}

뷰 모델이 상속됩니다.

public class MyViewModel : CloseableViewModel

그러면 당신이 보기에

public MyView()
{
    var viewModel = new StudyDataStructureViewModel(studyId);
    this.DataContext = viewModel;

    //InitializeComponent(); ...

    viewModel.ClosingRequest += (sender, e) => this.Close();
}

방법이 주어졌습니다. 확인하십시오.

https://stackoverflow.com/a/30546407/3659387

간단한 설명

  1. InNotify에서 View 모델 도출속성 변경됨
  2. 대화 상자를 닫으려면 언제든지 ViewModel, Change CloseDialog 속성에서 관찰 가능한 CloseDialog 속성을 만듭니다.
  3. 이 속성 변경에 대해 보기에서 처리기 연결
  4. 이제 거의 끝나가네요.이벤트 핸들러에서 DialogResult = true로 만듭니다.

우선 당신의 창문에 다음과 같은 이름을 붙입니다.

x:Name="AboutViewWindow"

닫기 버튼에서 명령 및 명령 매개 변수를 정의했습니다.

CommandParameter="{Binding ElementName=AboutViewWindow}"
Command="{Binding CancelCommand}"

그렇다면 내가 보기에

private ICommand _cancelCommand;        
public ICommand CancelCommand       
{
   get          
     {
        if (_cancelCommand == null)
           {
              _cancelCommand = new DelegateCommand<Window>(
                    x =>
                    {
                        x?.Close();
                    });
            }

            return _cancelCommand;          
     }      
}

Hanuman Institute를 사용하는 대부분의 MVVM 호환 솔루션.MvmDialogs

View 모델에 I-Closeable 인터페이스를 구현하면 끝입니다!

코드가 전혀 없습니다.

언급URL : https://stackoverflow.com/questions/11945821/implementing-close-window-command-with-mvvm

반응형