问题
I am currently working on a WPF project that utilizes Caliburn Micro and Caliburn.Micro.Telerik.
My issues are twofold. Firstly, if I create the View as a telerik:RadWindow then whenever the Show / ShowDialog method is called the window never gets displayed. If I create the view as UserControl then it will display.
Secondly TryClose() works fine without parameters but whenever I try and pass in true / false the window does not close.
For reference here are the pertinent pieces of code:
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);
}
}
Window Manager:
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;
}
}
New User View Model:
[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
}
Finally, from our 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);
}
If anyone has any ideas on what may be up I would be super grateful.
Thanks in advance
回答1:
The answer to the first part of your question can be found here. The key is to apply the default RadWindow Style to your main/shell window. Another tip: add the following to the ShellView Window so that your application shows up in the Taskbar.
xmlns:navigation="clr-namespace:Telerik.Windows.Controls.Navigation;assembly=Telerik.Windows.Controls.Navigation"
navigation:RadWindowInteropHelper.ShowInTaskbar="True"
来源:https://stackoverflow.com/questions/42124065/issues-using-telerik-radwindow-and-custom-windowmanager-in-caliburn-micro