【发布时间】:2016-05-08 18:23:36
【问题描述】:
我在 mvvm 中遇到了中介者模式的问题
为了更好地理解我的问题,我将描述几乎所有的类。
我有 MainWindow 和 ViewModel,它非常简单,实际上除了持有我的一个 UserControl 之外什么都不做,ViewModel 中有一个 UserControl 属性绑定到 MainWindow 中的 ContentControl.Content。
用户控件是相同的,每个控件中只有一个按钮, 并且还有两个 ViewModel 带有处理 clikcs 的命令。
Class Mediator 是一个单例,我尝试将它用于我的 ViewModel 之间的迭代
所以我要做的是在 UserControls 之间切换,而不是在 MainWindowViewModel 中创建它们和它们的 ViewModel。在我单击按钮后必须进行切换。例如,如果我单击 FirstUserControl 上的按钮,则 MainWindow 的 ContentControl 应切换到 SecondUserControl。
问题出现在 UserControlsViewModels 中,我应该在 Mediator NotifyCollegue() 函数中将 UserControls 对象作为参数传递,但我无法访问它们 (当然,这是 MVVM 的原理之一),这就是用户类型的问题,因为使用标准类型应该没有问题(例如传递 int 或 string...)。
我在这里找到了这个解决方案 http://www.codeproject.com/Articles/35277/MVVM-Mediator-Pattern
以及为什么我不能在 MainWindowViewModel 中切换 UserControls,因为我希望 MainWindow 清除除当前 UserControl 绑定到 ContentControl 之外的所有内容。
对于这个问题有什么可能的解决方案,我是否应该创建另一个单例类并在那里收集所有 userControls 引用并在 UserControlsViewModels 中使用它们,或者其他什么?
我希望我已经清楚地描述了我的问题,并且有某种解决方案。
我很乐意回答任何问题,非常感谢您的帮助!!!
哦,那不是真正的应用程序,我只是想了解 ViewModel 之间的消息系统的想法(概念),而不是混合 ViewModel 而不是在其他 ViewModel 中创建 View 及其 ViewModel...
再次感谢!
主视图
<Window x:Class="TESTPROJECT.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TESTPROJECT"
mc:Ignorable="d"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="500" Width="750">
<Grid>
<ContentControl Grid.Row="1" Content="{Binding PagesControl}"/>
</Grid>
主视图视图模型
namespace TESTPROJECT
{
class MainWindowViewModel : ViewModelBase
{
private UserControl _pagesControl;
public UserControl PagesControl
{
//Property that switches UserControls
set
{
_pagesControl = value;
OnPropertyChanged();
}
get
{
return _pagesControl;
}
}
public MainWindowViewModel()
{
//Method that will be listening all the changes from UserControls ViewModels
Mediator.Instance.Register(
(object obj) =>
{
PagesControl = obj as UserControl;
}, ViewModelMessages.UserWroteSomething);
}
}
}
FirstUserControl
<UserControl x:Class="TESTPROJECT.FirstUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TESTPROJECT"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button Command="{Binding GetCommand}">
hello, i'm first user control!
</Button>
</Grid>
FirstUserControl 视图模型
namespace TESTPROJECT
{
class FirstUserControlViewModel : ViewModelBase
{
//command that is binded to button
private DelegateCommand getCommand;
public ICommand GetCommand
{
get
{
if (getCommand == null)
getCommand = new DelegateCommand(param => this.func(param), null);
return getCommand;
}
}
//method that will handle button click, and in it i'm sending a message
//to MainWindowViewModel throug Mediator class
//and that is allso a problem place because in theory i should
//pass the opposite UserControl object , but from here i have no
//acces to it
private void func(object obj)
{
Mediator.Instance.NotifyColleagues(
ViewModelMessages.UserWroteSomething,
"PROBLEM PLACE");
}
}
}
第二用户控件
<UserControl x:Class="TESTPROJECT.SecondUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TESTPROJECT"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button Command="{Binding GetCommand}">
Hello, i'm second user control!
</Button>
</Grid>
SecondUserControl 视图模型
namespace TESTPROJECT
{
class SecondUserControlViewModel : ViewModelBase
{
//command that is binded to button
private DelegateCommand getCommand;
public ICommand GetCommand
{
get
{
if (getCommand == null)
getCommand = new DelegateCommand(param => this.func(param), null);
return getCommand;
}
}
//method that will handle button click, and in it i'm sending a message
//to MainWindowViewModel throug Mediator class
//and that is allso a problem place because in theory i should
//pass the opposite UserControl object , but from here i have no
//acces to it
private void func(object obj)
{
Mediator.Instance.NotifyColleagues(
ViewModelMessages.UserWroteSomething,
"PROBLEM PLACE");
}
}
}
类调解员 和 枚举 ViewModelMessages
namespace TESTPROJECT
{
//this enum holding some kind of event names fro example UserWroteSomething
// is a name of switching one UserControl to another
public enum ViewModelMessages { UserWroteSomething = 1 };
class Mediator
{
//Singletone part
private static Mediator instance;
public static Mediator Instance
{
get
{
if (instance == null)
instance = new Mediator();
return instance;
}
}
private Mediator() { }
//Singletone part
//collection listeners that holds event names and handler functions
List<KeyValuePair<ViewModelMessages, Action<Object>>> internalList =
new List<KeyValuePair<ViewModelMessages, Action<Object>>>();
//new listener registration
public void Register(Action<object> callBack, ViewModelMessages message)
{
internalList.Add(
new KeyValuePair<ViewModelMessages, Action<Object>>(message, callBack));
}
// notifying all the listener about some changes
// and those whose names fits will react
public void NotifyColleagues(ViewModelMessages message, object args)
{
foreach(KeyValuePair<ViewModelMessages, Action<Object>> KwP in internalList)
if(KwP.Key == message)
KwP.Value(args);
}
}
}
应用起点
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
FirstUserControl first = new FirstUserControl() { DataContext = new FirstUserControlViewModel() };
SecondUserControl second = new SecondUserControl() { DataContext = new SecondUserControlViewModel() };
new MainWindow()
{
DataContext = new MainWindowViewModel() { PagesControl = first }
}.ShowDialog();
}
}
【问题讨论】:
标签: c# wpf xaml mvvm user-controls