Winform dialog with WPF window as Parent - wpf

I have a WinForm dialog and I want to set its Parent property to a WPF window.
How can I do this?

Consider passing parameter to ShowDialog method instead of using Parent property.
You can write helper class
class Wpf32Window : IWin32Window
{
public IntPtr Handle { get; private set; }
public Wpf32Window(Window wpfWindow)
{
Handle = new WindowInteropHelper(wpfWindow).Handle;
}
}
public static class WindowExtensions
{
public static IWin32Window GetWin32Window (this Window parent)
{
return new Wpf32Window(parent);
}
}
After that you can just write
winFormsWindow.Show(yourWpfWindow.GetWin32Window());

Related

In which window should I instantiate my object?

My WPF application has multiple windows:
MainWindow
ChildWindow1
Childwindow2
I instantiate the children from MainWindow by...
public partial class MainWindow : Window
{
ChildWindow1 CW1;
ChildWindow2 CW2;
public MainWindow()
{
InitializeComponent();
}
private void btnButton1_Click(object sender, RoutedEventArgs e)
{
CW1 = new ChildWindow1();
CW1.Show();
CW1.Owner = this;
CW2 = new ChildWindow2();
CW2.Show();
CW2.Owner = this;
}
}
Awesome!
But here's where I run into trouble: I have a non-UI class that I need to instantiate.
public class MyClass
{
public void DoSomething()
{
//Do something here
}
}
The object of that class should "live" inside ChildWindow1, because that's where it logically belongs. So, I instantiate it inside ChildWindow1 like so:
public partial class ChildWindow1 : Window
{
public MyClass MyObject = new MyClass();
public ChildWindow1()
{
InitializeComponent();
}
}
But eventually comes a point where ChildWindow2 needs to interact with the object in ChildWindow1:
Call the 'DoSomething()' method of the object in Childwindow1.
Subscribe to an event raised by the object in ChildWindow1
I can do all that from the main window, because it owns the children, but I want the children to be able to interact directly.
Am I violating a design principle by allowing CW1 <--> CW2 interaction?
How else would you get them to interact if not by calling methods or subscribing to events?
Thanks to all here, for providing this awesome learning resource! Much appreciated!
Make this the instance of MyClass both public and static, to access it from almost anywhere because that should be accessed based on a certain instance of window.
If you wanna access a variable from any window, either make it static or call it based on an instance of that window like:
public partial class ChildWindow1 : Window
{
public static MyClass MyObject = new MyClass();
public ChildWindow1()
{
InitializeComponent();
}
}
access like this CW1.MyObject

How to make parent view bind command with child view-model method

I have a simpleButton in parent view and I want to bind this button with a method in child view-model.
_fluentApi.BindCommand(simpleButton , x => x.SaveMessage());
DevExpress MVVM Fluent API supports binding to nested properties/commands:
// ViewModel
public class ParentViewModel {
public ParentViewModel() {
Child = ChildViewModel.Create();
}
public virtual ChildViewModel Child {
get;
protected set;
}
}
public class ChildViewModel{
public static ChildViewModel Create() {
return DevExpress.Mvvm.POCO.ViewModelSource.Create<ChildViewModel>();
}
public void Save(){
// ...
}
}
// View
var fluentApi = mvvmContext.OfType<ParentViewModel>()
fluentApi.BindCommand(simpleButton , x => x.Child.Save());

How to close dialog window from viewmodel (Caliburn+WPF)?

I haveViewModel1 and View1 associated with it. I start dialog window from ViewModel2 (some another viewmodel) using IWindowManager object. The code from ViewModel2 class:
windowManager.ShowDialog(new ViewModel());
So, I have Dialog Window with View1 user control.
My answer is next - I can close that dialog window using red close button, but how to close it using my specific button (contained in View1 user control), something like "Cancel" button with close command (Command={Binding CancelCommand}), CancelCommand of course is contained in ViewModel1 class.
It's even easier if your view model extends Caliburn.Micro.Screen:
TryClose();
You can get the current view (in your case the dialog window) with implementing the IViewAware interface on your ViewModel. Then you can call Close on the the view (the Window created as the dialog) when your command is executed.
The easiest why is to derive from ViewAware:
public class DialogViewModel : ViewAware
{
public void ExecuteCancelCommand()
{
(GetView() as Window).Close();
}
}
If you are not allowed to derive you can implement it yourself:
public class DialogViewModel : IViewAware
{
public void ExecuteCancelCommand()
{
dialogWindow.Close();
}
private Window dialogWindow;
public void AttachView(object view, object context = null)
{
dialogWindow = view as Window;
if (ViewAttached != null)
ViewAttached(this,
new ViewAttachedEventArgs(){Context = context, View = view});
}
public object GetView(object context = null)
{
return dialogWindow;
}
public event EventHandler<ViewAttachedEventArgs> ViewAttached;
}
Note: I've used Caliburn.Micro 1.3.1 for my sample.
A cleaner way (Subject of personal taste) that I use alot is to use the IResult pattern, this way you abstract the Window implemenation
Viewmodel
public IEnumerable<IResult> CloseMe()
{
yield return new CloseResult();
}
Result code
public class CloseResult : Result
{
public override void Execute(ActionExecutionContext context)
{
var window = Window.GetWindow(context.View);
window.Close();
base.Execute(context);
}
}
public abstract class Result : IResult
{
public virtual void Execute(ActionExecutionContext context)
{
OnCompleted(this, new ResultCompletionEventArgs());
}
protected virtual void OnCompleted(object sender, ResultCompletionEventArgs e)
{
if (Completed != null)
Completed(sender, e);
}
public event EventHandler<ResultCompletionEventArgs> Completed;
}
edit (Only needed for IoC): If you wanna take it a step further you do a base class for all screens
public abstract class ShellPresentationModel : Screen
{
public ShellPresentationModel(IResultFactory resultFactory)
{
Result = resultFactory;
}
public IResultFactory Result { get; private set; }
}
This way you can inject dependencies with a IoC much easier, then your VIewmodel close method will look like this
public IEnumerable<IResult> CloseMe()
{
yield return Result.Close();
}
An example on a IResult that uses dependency can be
public class ShowDialogResult<TModel> : Result
{
private readonly IWindowManager windowManager;
private readonly TModel model;
private Action<TModel> configure;
public ShowDialogResult(IWindowManager windowManager, TModel model)
{
this.windowManager = windowManager;
this.model = model;
}
public IResult Configure(Action<TModel> configure)
{
this.configure = configure;
return this;
}
public override void Execute(ActionExecutionContext context)
{
if(configure != null)
configure(model);
windowManager.ShowDialog(model);
base.Execute(context);
}
}
edit Just noticed that i forgot to add an example of the above IoC exmaple, here goes
With a child IoC container pattern it would look like this
public IEnumerable<IResult> ShowDialog()
{
yield return Result.ShowDialog<MyViewModel>();
}
Without a child container pattern you would need to inject parent dependeync into the child manually
yield return Result.ShowDialog<MyViewModel>().Configure(m => m.SomeData = this.SomeData);

Open new Window from view model

Hi I have a beginner problem. I have shell (it is wpf window) and in this shell is screen (it is an user control / view model).
I would like open new window from view model, not show user control in shell.
So I create new window - ChatView
<Window x:Class="Spirit.Views.ChatView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended" Title="ChatView" Height="545" Width="763">
<Grid Margin="4,4,4,4">
</Grid>
</Window>
Export ChatViewModel with MEF.
public interface IChatViewModel
{
}
[Export("ChatScreen",typeof(IChatViewModel))]
public class ChatViewModel
{
}
In view model I have this method:
With ShowScreen class help me Mr.Marco Amendola. It look likes this:
public class ShowScreen : IResult
{
readonly Type _screenType;
readonly string _name;
[Import]
public IShellViewModel Shell { get; set; }
Action<object> _initializationAction = screen => { };
public ShowScreen InitializeWith<T>(T argument)
{
_initializationAction = screen =>
{
var initializable = screen as IInitializable<T>;
if (initializable != null)
initializable.Initialize(argument);
};
return this;
}
public ShowScreen(string name)
{
_name = name;
}
public ShowScreen(Type screenType)
{
_screenType = screenType;
}
public void Execute(ActionExecutionContext context)
{
var screen = !string.IsNullOrEmpty(_name)
? IoC.Get<object>(_name)
: IoC.GetInstance(_screenType, null);
_initializationAction(screen);
Shell.ActivateItem(screen);
Completed(this, new ResultCompletionEventArgs());
}
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
public static ShowScreen Of<T>()
{
return new ShowScreen(typeof(T));
}
}
My problem is if I try show new window it doesn’t works, it works only if I show new user control in shell(window).
I would like achieve behavior something like in skype. You have a main window with listbox, you double clicked on item and it show new chat window.
Main window can publish with EventAggregator on chat window and also chat window can publish on main window. This is my goal.
I know that I can not use class ShowScreen on showing new Window. I would like to know what is correct way to create new window from view model and inject event aggregator
to this vie model.
Any advice? Thank for your help and time.
Have you looked at WindowManager.Show or WindowManager.ShowDialog? Rob has a sample at http://caliburnmicro.codeplex.com/wikipage?title=The%20Window%20Manager. You can inject this dependency into your view model as IWindowManager.
I'm using this. Maybe could save a question about "where's the code ?".
DialogHelper:
public class DialogHelper
{
public void ShowDialog<T>(params Object[] param) where T : class
{
var windowManager = new WindowManager();
T viewModel = Activator.CreateInstance(typeof(T), param) as T;
windowManager.ShowWindow(viewModel);
}
}
How to use:
Without constructor parameter:
Dialog.ShowDialog<TestTableViewModel>();
With constructor paramater:
Dialog.ShowDialog<TestTableViewModel>(dt);
Note that I'm not using MEF

Cinch version of ViewModel command to close a View

Without wanting to bug sacha too much, does anyone know what the Cinch V2 way of closing a View from a ViewModel command?
Previously I have used a RelayCommand in the ViewModel base to accept the Escape keybinding command action and wired up a RequestClose event in the View code behind to do this.
Use CloseActivePopUpCommand.Execute(true) in the execute method to close a view.
I've included a short sample below.
[ExportViewModel("PickOperatorViewModel")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class PickOperatorViewModel : ViewModelBase
{
[ImportingConstructor]
public PickOperatorViewModel()
{
PickOperaterCommand = new SimpleCommand<Object, Object>(CanExecutePickOperaterCommand, ExecutePickOperaterCommand);
}
public SimpleCommand<Object, Object> PickOperaterCommand { get; private set; }
private void ExecutePickOperaterCommand(Object args)
{
CloseActivePopUpCommand.Execute(true);
}
private bool CanExecutePickOperaterCommand(Object args)
{
return true;
}
}

Resources