<legend id='z5vjf'><style id='z5vjf'><dir id='z5vjf'><q id='z5vjf'></q></dir></style></legend>

    <small id='z5vjf'></small><noframes id='z5vjf'>

    <tfoot id='z5vjf'></tfoot>
    • <bdo id='z5vjf'></bdo><ul id='z5vjf'></ul>
    <i id='z5vjf'><tr id='z5vjf'><dt id='z5vjf'><q id='z5vjf'><span id='z5vjf'><b id='z5vjf'><form id='z5vjf'><ins id='z5vjf'></ins><ul id='z5vjf'></ul><sub id='z5vjf'></sub></form><legend id='z5vjf'></legend><bdo id='z5vjf'><pre id='z5vjf'><center id='z5vjf'></center></pre></bdo></b><th id='z5vjf'></th></span></q></dt></tr></i><div id='z5vjf'><tfoot id='z5vjf'></tfoot><dl id='z5vjf'><fieldset id='z5vjf'></fieldset></dl></div>

    1. 使用 MVVM 在 wpf 中使用 Dialogs 的好坏习惯?

      时间:2023-10-05

      1. <i id='L29zc'><tr id='L29zc'><dt id='L29zc'><q id='L29zc'><span id='L29zc'><b id='L29zc'><form id='L29zc'><ins id='L29zc'></ins><ul id='L29zc'></ul><sub id='L29zc'></sub></form><legend id='L29zc'></legend><bdo id='L29zc'><pre id='L29zc'><center id='L29zc'></center></pre></bdo></b><th id='L29zc'></th></span></q></dt></tr></i><div id='L29zc'><tfoot id='L29zc'></tfoot><dl id='L29zc'><fieldset id='L29zc'></fieldset></dl></div>
          <tfoot id='L29zc'></tfoot>
            <tbody id='L29zc'></tbody>

          <small id='L29zc'></small><noframes id='L29zc'>

          1. <legend id='L29zc'><style id='L29zc'><dir id='L29zc'><q id='L29zc'></q></dir></style></legend>

                <bdo id='L29zc'></bdo><ul id='L29zc'></ul>
                本文介绍了使用 MVVM 在 wpf 中使用 Dialogs 的好坏习惯?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我最近遇到了为我的 wpf 应用程序创建添加和编辑对话框的问题.

                I lately had the problem of creating add and edit dialogs for my wpf app.

                我想要在我的代码中做的就是这样.(我主要使用 mvvm 的视图模型优先方法)

                All I want to do in my code was something like this. (I mostly use viewmodel first approach with mvvm)

                调用对话窗口的ViewModel:

                ViewModel which calls a dialog window:

                var result = this.uiDialogService.ShowDialog("Dialogwindow Title", dialogwindowVM);
                // Do anything with the dialog result
                

                它是如何工作的?

                首先,我创建了一个对话服务:

                First, I created a dialog service:

                public interface IUIWindowDialogService
                {
                    bool? ShowDialog(string title, object datacontext);
                }
                
                public class WpfUIWindowDialogService : IUIWindowDialogService
                {
                    public bool? ShowDialog(string title, object datacontext)
                    {
                        var win = new WindowDialog();
                        win.Title = title;
                        win.DataContext = datacontext;
                
                        return win.ShowDialog();
                    }
                }
                

                WindowDialog 是一个特殊但简单的窗口.我需要它来保存我的内容:

                WindowDialog is a special but simple window. I need it to hold my content:

                <Window x:Class="WindowDialog"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    Title="WindowDialog" 
                    WindowStyle="SingleBorderWindow" 
                    WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
                    <ContentPresenter x:Name="DialogPresenter" Content="{Binding .}">
                
                    </ContentPresenter>
                </Window>
                

                wpf 中对话框的一个问题是 dialogresult = true 只能在代码中实现.这就是为什么我为我的 dialogviewmodel 创建了一个接口来实现它.

                A problem with dialogs in wpf is the dialogresult = true can only be achieved in code. That's why I created an interface for my dialogviewmodel to implement it.

                public class RequestCloseDialogEventArgs : EventArgs
                {
                    public bool DialogResult { get; set; }
                    public RequestCloseDialogEventArgs(bool dialogresult)
                    {
                        this.DialogResult = dialogresult;
                    }
                }
                
                public interface IDialogResultVMHelper
                {
                    event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog;
                }
                

                每当我的 ViewModel 认为是 dialogresult = true 的时候了,就引发这个事件.

                Whenever my ViewModel thinks it's time for dialogresult = true, then raise this event.

                public partial class DialogWindow : Window
                {
                    // Note: If the window is closed, it has no DialogResult
                    private bool _isClosed = false;
                
                    public DialogWindow()
                    {
                        InitializeComponent();
                        this.DialogPresenter.DataContextChanged += DialogPresenterDataContextChanged;
                        this.Closed += DialogWindowClosed;
                    }
                
                    void DialogWindowClosed(object sender, EventArgs e)
                    {
                        this._isClosed = true;
                    }
                
                    private void DialogPresenterDataContextChanged(object sender,
                                              DependencyPropertyChangedEventArgs e)
                    {
                        var d = e.NewValue as IDialogResultVMHelper;
                
                        if (d == null)
                            return;
                
                        d.RequestCloseDialog += new EventHandler<RequestCloseDialogEventArgs>
                                                    (DialogResultTrueEvent).MakeWeak(
                                                        eh => d.RequestCloseDialog -= eh;);
                    }
                
                    private void DialogResultTrueEvent(object sender, 
                                              RequestCloseDialogEventArgs eventargs)
                    {
                        // Important: Do not set DialogResult for a closed window
                        // GC clears windows anyways and with MakeWeak it
                        // closes out with IDialogResultVMHelper
                        if(_isClosed) return;
                
                        this.DialogResult = eventargs.DialogResult;
                    }
                 }
                

                现在至少我必须在我的资源文件(app.xaml 或其他东西)中创建一个 DataTemplate:

                Now at least I have to create a DataTemplate in my resource file(app.xaml or something):

                <DataTemplate DataType="{x:Type DialogViewModel:EditOrNewAuswahlItemVM}" >
                        <DialogView:EditOrNewAuswahlItem/>
                </DataTemplate>
                

                就是这样,我现在可以从我的视图模型中调用对话框:

                Well thats all, I can now call dialogs from my viewmodels:

                 var result = this.uiDialogService.ShowDialog("Dialogwindow Title", dialogwindowVM);
                

                现在我的问题是,你觉得这个解决方案有什么问题吗?

                Now my question, do you see any problems with this solution?

                为了完整性.ViewModel 应该实现 IDialogResultVMHelper 然后它可以在 OkCommand 或类似的东西中引发它:

                for completeness. The ViewModel should implement IDialogResultVMHelper and then it can raise it within a OkCommand or something like this:

                public class MyViewmodel : IDialogResultVMHelper
                {
                    private readonly Lazy<DelegateCommand> _okCommand;
                
                    public MyViewmodel()
                    {
                         this._okCommand = new Lazy<DelegateCommand>(() => 
                             new DelegateCommand(() => 
                                 InvokeRequestCloseDialog(
                                     new RequestCloseDialogEventArgs(true)), () => 
                                         YourConditionsGoesHere = true));
                    }
                
                    public ICommand OkCommand
                    { 
                        get { return this._okCommand.Value; } 
                    }
                
                    public event EventHandler<RequestCloseDialogEventArgs> RequestCloseDialog;
                    private void InvokeRequestCloseDialog(RequestCloseDialogEventArgs e)
                    {
                        var handler = RequestCloseDialog;
                        if (handler != null) 
                            handler(this, e);
                    }
                 }
                

                编辑 2:我使用此处的代码使 EventHandler 寄存器变弱:
                http://diditwith.net/2007/03/23/SolvingTheProblemWithEventsWeakEventHandlers.aspx
                (网站不再存在,WebArchive镜子)

                EDIT 2: I used the code from here to make my EventHandler register weak:
                http://diditwith.net/2007/03/23/SolvingTheProblemWithEventsWeakEventHandlers.aspx
                (Website no longer exists, WebArchive Mirror)

                public delegate void UnregisterCallback<TE>(EventHandler<TE> eventHandler) 
                    where TE : EventArgs;
                
                public interface IWeakEventHandler<TE> 
                    where TE : EventArgs
                {
                    EventHandler<TE> Handler { get; }
                }
                
                public class WeakEventHandler<T, TE> : IWeakEventHandler<TE> 
                    where T : class 
                    where TE : EventArgs
                {
                    private delegate void OpenEventHandler(T @this, object sender, TE e);
                
                    private readonly WeakReference mTargetRef;
                    private readonly OpenEventHandler mOpenHandler;
                    private readonly EventHandler<TE> mHandler;
                    private UnregisterCallback<TE> mUnregister;
                
                    public WeakEventHandler(EventHandler<TE> eventHandler,
                                                UnregisterCallback<TE> unregister)
                    {
                        mTargetRef = new WeakReference(eventHandler.Target);
                
                        mOpenHandler = (OpenEventHandler)Delegate.CreateDelegate(
                                           typeof(OpenEventHandler),null, eventHandler.Method);
                
                        mHandler = Invoke;
                        mUnregister = unregister;
                    }
                
                    public void Invoke(object sender, TE e)
                    {
                        T target = (T)mTargetRef.Target;
                
                        if (target != null)
                            mOpenHandler.Invoke(target, sender, e);
                        else if (mUnregister != null)
                        {
                            mUnregister(mHandler);
                            mUnregister = null;
                        }
                    }
                
                    public EventHandler<TE> Handler
                    {
                        get { return mHandler; }
                    }
                
                    public static implicit operator EventHandler<TE>(WeakEventHandler<T, TE> weh)
                    {
                        return weh.mHandler;
                    }
                }
                
                public static class EventHandlerUtils
                {
                    public static EventHandler<TE> MakeWeak<TE>(this EventHandler<TE> eventHandler, 
                                                                    UnregisterCallback<TE> unregister)
                        where TE : EventArgs
                    {
                        if (eventHandler == null)
                            throw new ArgumentNullException("eventHandler");
                
                        if (eventHandler.Method.IsStatic || eventHandler.Target == null)
                            throw new ArgumentException("Only instance methods are supported.",
                                                            "eventHandler");
                
                        var wehType = typeof(WeakEventHandler<,>).MakeGenericType(
                                          eventHandler.Method.DeclaringType, typeof(TE));
                
                        var wehConstructor = wehType.GetConstructor(new Type[] 
                                             { 
                                                 typeof(EventHandler<TE>), typeof(UnregisterCallback<TE>) 
                                             });
                
                        IWeakEventHandler<TE> weh = (IWeakEventHandler<TE>)wehConstructor.Invoke(
                                                        new object[] { eventHandler, unregister });
                
                        return weh.Handler;
                    }
                }
                

                推荐答案

                这是一个很好的方法,我过去也使用过类似的方法.加油!

                This is a good approach and I used similar ones in the past. Go for it!

                当您需要在 DialogResult 中设置false"时,我肯定会做的一件小事就是让事件接收一个布尔值.

                One minor thing I'd definitely do is make the event receive a boolean for when you need to set "false" in the DialogResult.

                event EventHandler<RequestCloseEventArgs> RequestCloseDialog;
                

                和 EventArgs 类:

                and the EventArgs class:

                public class RequestCloseEventArgs : EventArgs
                {
                    public RequestCloseEventArgs(bool dialogResult)
                    {
                        this.DialogResult = dialogResult;
                    }
                
                    public bool DialogResult { get; private set; }
                }
                

                这篇关于使用 MVVM 在 wpf 中使用 Dialogs 的好坏习惯?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:将值从一个表单发送到另一个表单 下一篇:'await' 运算符只能在异步 lambda 表达式中使用

                相关文章

                    <i id='PgkwZ'><tr id='PgkwZ'><dt id='PgkwZ'><q id='PgkwZ'><span id='PgkwZ'><b id='PgkwZ'><form id='PgkwZ'><ins id='PgkwZ'></ins><ul id='PgkwZ'></ul><sub id='PgkwZ'></sub></form><legend id='PgkwZ'></legend><bdo id='PgkwZ'><pre id='PgkwZ'><center id='PgkwZ'></center></pre></bdo></b><th id='PgkwZ'></th></span></q></dt></tr></i><div id='PgkwZ'><tfoot id='PgkwZ'></tfoot><dl id='PgkwZ'><fieldset id='PgkwZ'></fieldset></dl></div>

                    <legend id='PgkwZ'><style id='PgkwZ'><dir id='PgkwZ'><q id='PgkwZ'></q></dir></style></legend>

                    <small id='PgkwZ'></small><noframes id='PgkwZ'>

                  1. <tfoot id='PgkwZ'></tfoot>
                      <bdo id='PgkwZ'></bdo><ul id='PgkwZ'></ul>