我的主窗口上有一个按钮。当我点击它时,我希望在主窗口顶部弹出另一个窗口。
主窗口仍然可见,应该是这个新窗口的父窗口。
我一直在寻找并且不确定如何做到这一点,有些人建议使用Messenger来做到这一点,但并没有真正举一个例子。
答案 0 :(得分:0)
嗨我没有MVVMLight所以我使用了自定义Messanger,因为它可以让图片更加清晰。
消息类型
public enum MessageType
{
DataLoaded,
OpenWindow,
SetFocus,
OpenExceptionWindow,
Refresh
//etc
}
消息
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; }
}
信使
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)
{
}
}
查看
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这里的第一个元素不是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));
}
}
视图模型
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"));
}
}
我希望这会有所帮助。这是一个易于理解的简单代码。