1

I have a button on my Main Window. When I click it I want another Window to popup on top of the Main Window.

Main Window is still visible and should be the parent of this new window.

I been looking around and not sure how to do it, some people suggested to use the Messenger to do this but did not really give an example.

chobo2
  • 83,322
  • 195
  • 530
  • 832
  • Please see this link for an example http://stackoverflow.com/questions/3386349/how-to-open-a-new-window-using-mvvm-light-toolkit – MoZahid Jan 10 '14 at 22:13
  • Please see this link for an example http://stackoverflow.com/questions/3386349/how-to-open-a-new-window-using-mvvm-light-toolkit – MoZahid Jan 10 '14 at 22:14
  • Ya, I am looking at that one and was able to implement it. I trying to figure out how to how to set the child windows owner then. In the comments it talks about "RootVisual" but not sure how to use it and it seems to create a dependency so not sure if there is a better way. – chobo2 Jan 10 '14 at 22:19
  • are you using some sort of service that is incharge of loading showing the new window? – MoZahid Jan 10 '14 at 22:23
  • Nope, Pretty much I got a RelayCommand in my ViewModel that now Sends out the Message that gets caught in the View Codebehind and makes the new Window. – chobo2 Jan 10 '14 at 22:27
  • Hi I think you might be able it set the owner of the new window by getting application.current.mainwindow then setting that as the parent – MoZahid Jan 10 '14 at 22:47
  • You may want to try Extended WPF Toolkit's [ChildWindow](http://wpftoolkit.codeplex.com/wikipage?title=ChildWindow) – har07 Jan 11 '14 at 01:41
  • @har07 - is it MVVM friendly? if so do you have an example? – chobo2 Jan 13 '14 at 17:20

1 Answers1

0

Hi I didnt have MVVMLight so I have used custom Messanger because to make picture clearer how things work.

MessageType

public enum MessageType
{ 
    DataLoaded,
    OpenWindow,
    SetFocus,
    OpenExceptionWindow,
    Refresh
    //etc
}

Message

public class Message
{
    public Message(MessageType messageType, object message)
    {
        MessageType = messageType;
        MessageObject = message;
    }

    public MessageType MessageType { get; private set; }
    public object MessageObject { get; private set; }
}

Messanger

    public class Messanger
{
    //Singleton
    private Messanger()
    { }

    static Messanger instance;
    public static Messanger Instance
    { 
        get{return instance ?? (instance=new Messanger());}
    }

    static Dictionary<string, Action<Message>> dictionary = new Dictionary<string, Action<Message>>();

    //View Calls this and register the delegate corresponding to the unique token
    public void Register(string token,Action<Message> action)
    {
        if (dictionary.ContainsKey(token))
            throw new Exception("Already registered");
        if (action == null)
            throw new ArgumentNullException("action is null");

        dictionary.Add(token, action);
    }

    public void UnRegister(string token)
    { 
        if(dictionary.ContainsKey(token))
            dictionary.Remove(token);
    }

    //ViewModel Calls this and pass the token and Message.
    //the registered delegate is looked up in dictionary corresponding to that token and
    //Corresponding register delegate fired.
    public void SendMessage(string token,Message message)
    {
        if (dictionary.ContainsKey(token))
            dictionary[token](message);
    }
}

ViewBase

 public class ViewBase:Window
{
    protected  string Token { get; private set; }

    public ViewBase()
    {
        Token = Guid.NewGuid().ToString();

        //Register to Messanger
        Messanger.Instance.Register(Token, HandleMessages);

        //UnRegister On Closing or Closed
        this.Closing +=(s,e)=> Messanger.Instance.UnRegister(Token);
    }

    //Handle Common Messages to all Windows Here
    void HandleMessages(Message message)
    {
        switch (message.MessageType)
        { 
            case MessageType.OpenExceptionWindow:
                Exception ex = message.MessageObject as Exception;
                ExceptionWindow window = new ExceptionWindow();
                window.Exception = ex;
                window.ShowDialog();
                break;
                //other common cases should be handled here

            default : HandleWindowLevelMessage(message);
                break;

        }

    }

    protected virtual void HandleWindowLevelMessage(Message message)
    { 

    }

}

View

public partial class Mywindow : ViewBase
{
    public Mywindow()
    {
        InitializeComponent();
        DataContext = new MyViewModel(Token);
    }

    protected override void HandleWindowLevelMessage(Message message)
    {
        //open window according to OP Requirement
        if (message.MessageType == MessageType.OpenWindow)
        {
            string windowName = message.ToString();

            if (windowName != null)
            {
                //logic to get the window . I assume that OP have some logic to get the child window this is just temporary
                var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(s=>s.Name==windowName);
                if (window != null)
                {
                   window.Owner=this;
                    window.Show();
                }
            }
        }

        base.HandleWindowLevelMessage(message);
    }
}

View.xaml Here first element is not Window now

<local:ViewBase x:Class="WpfApplication4.Mywindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication4"
    Title="Mywindow" Height="300" Width="300">
<Grid>
    <Button Content="ok" Click="Button_Click_1"/>
</Grid>

ViewModelBase

public class ViewModelBase : INotifyPropertyChanged
{
    public ViewModelBase(string token)
    {
        Token = token;
    }

    protected string Token { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    void RaisePropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

ViewModel

public class MyViewModel : ViewModelBase
{
    public MyViewModel(string token)
        : base(token)
    {

    }

    //say OP want to open window on Command Execute
    public void OnCommand()
    {
        Messanger.Instance.SendMessage(Token, new Message(MessageType.OpenWindow, "MyChildWindow"));
    }
}

I hope this will help. This is simple code to understand feel free to ask.

yo chauhan
  • 12,079
  • 4
  • 39
  • 58