在Caliburn Micro中使用Telerik RadWindow和自定义WindowManager的问题

时间:2017-02-08 21:35:34

标签: c# wpf telerik caliburn.micro

我目前正在开发一个利用Caliburn Micro和Caliburn.Micro.Telerik的WPF项目。

我的问题是双重的。首先,如果我创建View作为telerik:RadWindow,那么每当调用Show / ShowDialog方法时,窗口永远不会显示。如果我将视图创建为UserControl,那么它将显示。

其次TryClose()在没有参数的情况下工作正常,但每当我尝试传入true / false时,窗口都不会关闭。

以下是相关的代码:

Window Manager Extensions:

public static class IWindowManagerExtensions
{
    /// <summary>
    /// Opens an Alert modal window
    /// </summary>
    public static void Alert(this IWindowManager windowManager, string title, string message)
    {
        TelerikWindowManager.Alert(title, message);
    }

    /// <summary>
    /// Opens an Alert modal window
    /// </summary>
    public static void Alert(this IWindowManager windowManager, DialogParameters dialogParameters)
    {
        TelerikWindowManager.Alert(dialogParameters);
    }

    /// <summary>
    /// Opens a Confirm modal window
    /// </summary>
    public static void Confirm(this IWindowManager windowManager, string title, string message, System.Action onOK, System.Action onCancel = null)
    {
        TelerikWindowManager.Confirm(title, message, onOK, onCancel);
    }

    /// <summary>
    /// Opens a Confirm modal window
    /// </summary>
    public static void Confirm(this IWindowManager windowManager, DialogParameters dialogParameters)
    {
        TelerikWindowManager.Confirm(dialogParameters);
    }

    /// <summary>
    /// Opens a Prompt modal window
    /// </summary>
    public static void Prompt(this IWindowManager windowManager, string title, string message, string defaultPromptResultValue, Action<string> onOK)
    {
        TelerikWindowManager.Prompt(title, message, defaultPromptResultValue, onOK);
    }

    /// <summary>
    /// Opens a Prompt modal window
    /// </summary>
    public static void Prompt(this IWindowManager windowManager, DialogParameters dialogParameters)
    {
        TelerikWindowManager.Prompt(dialogParameters);
    }
}

窗口管理器:

    public class TelerikWindowManager : WindowManager
{
    public override bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null)
    {
        var viewType = ViewLocator.LocateTypeForModelType(rootModel.GetType(), null, null);
        if (typeof(RadWindow).IsAssignableFrom(viewType)
            || typeof(UserControl).IsAssignableFrom(viewType))
        {
            var radWindow = CreateRadWindow(rootModel, true, context, settings);
            radWindow.ShowDialog();
            return radWindow.DialogResult;
        }

        return base.ShowDialog(rootModel, context, settings);
    }

    public override void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null)
    {
        var viewType = ViewLocator.LocateTypeForModelType(rootModel.GetType(), null, null);
        if (typeof(RadWindow).IsAssignableFrom(viewType)
            || typeof(UserControl).IsAssignableFrom(viewType))
        {
            NavigationWindow navWindow = null;

            if (Application.Current != null && Application.Current.MainWindow != null)
            {
                navWindow = Application.Current.MainWindow as NavigationWindow;
            }

            if (navWindow != null)
            {
                var window = CreatePage(rootModel, context, settings);
                navWindow.Navigate(window);
            }
            else
            {
                CreateRadWindow(rootModel, false, context, settings).Show();
            }
            return;
        }
        base.ShowWindow(rootModel, context, settings);
    }


    /// <summary>
    /// Creates a window.
    /// </summary>
    /// <param name="rootModel">The view model.</param>
    /// <param name="isDialog">Whethor or not the window is being shown as a dialog.</param>
    /// <param name="context">The view context.</param>
    /// <param name="settings">The optional popup settings.</param>
    /// <returns>The window.</returns>
    protected virtual RadWindow CreateRadWindow(object rootModel, bool isDialog, object context, IDictionary<string, object> settings)
    {
        var view = EnsureRadWindow(rootModel, ViewLocator.LocateForModel(rootModel, null, context), isDialog);
        ViewModelBinder.Bind(rootModel, view, context);

        var haveDisplayName = rootModel as IHaveDisplayName;
        if (haveDisplayName != null && !ConventionManager.HasBinding(view, RadWindow.HeaderProperty))
        {
            var binding = new Binding("DisplayName") { Mode = BindingMode.TwoWay };
            view.SetBinding(RadWindow.HeaderProperty, binding);
        }

        ApplyRadWindowSettings(view, settings);

        new RadWindowConductor(rootModel, view);

        return view;
    }

    bool ApplyRadWindowSettings(object target, IEnumerable<KeyValuePair<string, object>> settings)
    {
        if (settings != null)
        {
            var type = target.GetType();

            foreach (var pair in settings)
            {
                var propertyInfo = type.GetProperty(pair.Key);

                if (propertyInfo != null)
                {
                    propertyInfo.SetValue(target, pair.Value, null);
                }
            }

            return true;
        }

        return false;
    }

    /// <summary>
    /// Makes sure the view is a window is is wrapped by one.
    /// </summary>
    /// <param name="model">The view model.</param>
    /// <param name="view">The view.</param>
    /// <param name="isDialog">Whethor or not the window is being shown as a dialog.</param>
    /// <returns>The window.</returns>
    protected virtual RadWindow EnsureRadWindow(object model, object view, bool isDialog)
    {
        var window = view as RadWindow;

        if (window == null)
        {
            var contentElement = view as FrameworkElement;
            if (contentElement == null)
                throw new ArgumentNullException("view");

            window = new RadWindow
            {
                Content = view,
                SizeToContent = true,
            };

            AdjustWindowAndContentSize(window, contentElement);

            window.SetValue(View.IsGeneratedProperty, true);

            var owner = GetActiveWindow();
            if (owner != null)
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                window.Owner = owner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
        }
        else
        {
            var owner = GetActiveWindow();
            if (owner != null && isDialog)
            {
                window.Owner = owner;
            }
        }

        return window;
    }

    /// <summary>
    /// Initializes Window size with values extracted by the view.
    /// 
    /// Note:
    /// The real size of the content will be smaller than provided values.
    /// The form has the header (title) and border so they will take place.
    /// 
    /// </summary>
    /// <param name="window">The RadWindow</param>
    /// <param name="view">The view</param>
    private static void AdjustWindowAndContentSize(RadWindow window, FrameworkElement view)
    {
        window.MinWidth = view.MinWidth;
        window.MaxWidth = view.MaxWidth;
        window.Width = view.Width;
        window.MinHeight = view.MinHeight;
        window.MaxHeight = view.MaxHeight;
        window.Height = view.Height;

        // Resetting view's settings
        view.Width = view.Height = Double.NaN;
        view.MinWidth = view.MinHeight = 0;
        view.MaxWidth = view.MaxHeight = int.MaxValue;

        // Stretching content to the Window
        view.VerticalAlignment = VerticalAlignment.Stretch;
        view.HorizontalAlignment = HorizontalAlignment.Stretch;
    }

    /// <summary>
    /// Infers the owner of the window.
    /// </summary>
    /// <returns>The owner.</returns>
    protected virtual Window GetActiveWindow()
    {
        if (Application.Current == null)
        {
            return null;
        }

        var active = Application.Current
            .Windows.OfType<Window>()
            .FirstOrDefault(x => x.IsActive);

        return active ?? Application.Current.MainWindow;
    }

    public static void Alert(string title, string message)
    {
        RadWindow.Alert(new DialogParameters { Header = title, Content = message });
    }

    public static void Alert(DialogParameters dialogParameters)
    {
        RadWindow.Alert(dialogParameters);
    }

    public static void Confirm(string title, string message, System.Action onOK, System.Action onCancel = null)
    {
        var dialogParameters = new DialogParameters
        {
            Header = title,
            Content = message
        };
        dialogParameters.Closed += (sender, args) =>
        {
            var result = args.DialogResult;
            if (result.HasValue && result.Value)
            {
                onOK();
                return;
            }

            if (onCancel != null)
                onCancel();
        };
        Confirm(dialogParameters);
    }

    public static void Confirm(DialogParameters dialogParameters)
    {
        RadWindow.Confirm(dialogParameters);
    }

    public static void Prompt(string title, string message, string defaultPromptResultValue, Action<string> onOK)
    {
        var dialogParameters = new DialogParameters
        {
            Header = title,
            Content = message,
            DefaultPromptResultValue = defaultPromptResultValue,
        };
        dialogParameters.Closed += (o, args) =>
        {
            if (args.DialogResult.HasValue && args.DialogResult.Value)
                onOK(args.PromptResult);
        };

        Prompt(dialogParameters);
    }

    public static void Prompt(DialogParameters dialogParameters)
    {
        RadWindow.Prompt(dialogParameters);
    }

}

Rad Window Conductor:

internal class RadWindowConductor
{
    private bool deactivatingFromView;
    private bool deactivateFromViewModel;
    private bool actuallyClosing;
    private readonly RadWindow view;
    private readonly object model;

    public RadWindowConductor(object model, RadWindow view)
    {
        this.model = model;
        this.view = view;

        var activatable = model as IActivate;
        if (activatable != null)
        {
            activatable.Activate();
        }

        var deactivatable = model as IDeactivate;
        if (deactivatable != null)
        {
            view.Closed += Closed;
            deactivatable.Deactivated += Deactivated;
        }

        var guard = model as IGuardClose;
        if (guard != null)
        {
            view.PreviewClosed += PreviewClosed;
        }
    }

    private void Closed(object sender, EventArgs e)
    {
        view.Closed -= Closed;
        view.PreviewClosed -= PreviewClosed;

        if (deactivateFromViewModel)
        {
            return;
        }

        var deactivatable = (IDeactivate)model;

        deactivatingFromView = true;
        deactivatable.Deactivate(true);
        deactivatingFromView = false;
    }

    private void Deactivated(object sender, DeactivationEventArgs e)
    {
        if (!e.WasClosed)
        {
            return;
        }

        ((IDeactivate)model).Deactivated -= Deactivated;

        if (deactivatingFromView)
        {
            return;
        }

        deactivateFromViewModel = true;
        actuallyClosing = true;
        view.Close();
        actuallyClosing = false;
        deactivateFromViewModel = false;
    }

    private void PreviewClosed(object sender, WindowPreviewClosedEventArgs e)
    {
        if (e.Cancel == true)
        {
            return;
        }

        var guard = (IGuardClose)model;

        if (actuallyClosing)
        {
            actuallyClosing = false;
            return;
        }

        bool runningAsync = false, shouldEnd = false;

        guard.CanClose(canClose =>
        {
            Execute.OnUIThread(() =>
            {
                if (runningAsync && canClose)
                {
                    actuallyClosing = true;
                    view.Close();
                }
                else
                {
                    e.Cancel = !canClose;
                }

                shouldEnd = true;
            });
        });

        if (shouldEnd)
        {
            return;
        }

        e.Cancel = true;
        runningAsync = true;
    }
}

新用户视图模型:

    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
[ExportController("NewUserViewModel")]
public class NewUserViewModel : FeatureWindowBase
{
    #region Fields
    private User _creatingUser;
    private User _userToAdd;
    #endregion

    #region Properties

    public bool IsOpen;

    public User UserToAdd
    {
        get
        {
            return _userToAdd;

        }
        set
        {
            _userToAdd = value; 
            NotifyOfPropertyChange(() => UserToAdd);
        }
    }

    public IEnumerable<Entity> AddedUsers => new List<Entity>() { UserToAdd };

    #endregion


    #region Constructors

    [ImportingConstructor]
    public NewUserViewModel(IWindowManager windowManager,
        IEventAggregator eventAggregator,
        IEntityManagerProvider<BearPawEntities> entityManagerProvider,
        IGlobalCache globalCache) :
        base(windowManager, eventAggregator, entityManagerProvider, globalCache)
    {
    }

    #endregion

    protected override void OnViewLoaded(object view)
    {
        base.OnViewLoaded(view);

        // un-comment the following if you want to use the Global Cache
        SetupGlobalCache<User>(Manager);
        _creatingUser = Manager.Users.FirstOrDefault(u => u.UserName ==
                                                 Manager.AuthenticationContext.Principal.Identity
                                                     .Name);

        UserToAdd = new User()
        {
            CreatedBy = _creatingUser,
            CreatedDate = DateTime.Now,
            ModifiedBy = _creatingUser,
            ModifiedDate = DateTime.Now
        };

        DisplayName = "Add New User";
        IsOpen = true;
    }

    #region Methods


    public async Task CreateUser()
    {
        try
        {

            var newAuth = new UserAuthentication()
            {
                Password = Security.CreateSaltedPasswordForNewUser("LetMeIn"),
                Salt = Security.LastSalt,
                CreatedBy = _creatingUser,
                CreatedDate = DateTime.Now,
                ModifiedBy = _creatingUser,
                ModifiedDate = DateTime.Now
            };


            Security.ClearLastSalt();

            Manager.AddEntity(newAuth);
            UserToAdd.UserAuthentication = newAuth;

            Manager.AddEntity(UserToAdd);

            var saveResponse = await Manager.TrySaveChangesAsync();

            if (saveResponse.Ok)
            {
                TryClose(true);
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

    #endregion

}

最后,来自我们的App Bootstrapper:

        protected override void Configure()
    {
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("xunit.*");
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("BearPaw.Client.*");
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("BearPaw.Clients.*");
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("Caliburn.*");
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("JetBrains.*");
        IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("FluentAssertions.*");

        var conventions = new RegistrationBuilder();
        conventions.ForTypesDerivedFrom<IBearPawFeature>()
            .Export()
            .SetCreationPolicy(CreationPolicy.NonShared);


        _container = new CompositionContainer(
            new AggregateCatalog(
                AssemblySource.Instance.Select(x=> new AssemblyCatalog(x, conventions)).OfType<ComposablePartCatalog>()
                )
            );

        var batch = new CompositionBatch();

        batch.AddExportedValue<IWindowManager>(new TelerikWindowManager());
        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue<IEntityManagerProvider<BearPawEntities>>(new MainEntityManagerProvider());
        batch.AddExportedValue<IEntityManagerProvider<BearPawReportingEntities>>(new ReportingEntityManagerProvider());
        batch.AddExportedValue(_container);

        // This is essential to enable Telerik's conventions
        TelerikConventions.Install();

        AddKeyBindingTriggers();

        VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Dark);
        VisualStudio2013Palette.Palette.BasicColor = Color.FromArgb(255, 77, 77, 82);


        _container.Compose(batch);
    }

如果有人对可能出现的事情有任何想法,我将非常感激。

提前致谢

1 个答案:

答案 0 :(得分:0)

可以找到问题的第一部分的答案here.,关键是将默认的RadWindow Style应用于主/ shell窗口。另一个提示:将以下内容添加到ShellView窗口中,以便您的应用程序显示在任务栏中。

    xmlns:navigation="clr-namespace:Telerik.Windows.Controls.Navigation;assembly=Telerik.Windows.Controls.Navigation"
    navigation:RadWindowInteropHelper.ShowInTaskbar="True"