- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试在 WPF/MVVM 应用程序中实现 Mediator 模式,以使 ViewModel 之间的通信成为可能。
为了应用中介模式,我从 this link 下载了一个示例项目。 。然后我从示例中学到了它,然后应用到我的示例项目中。
我在使用这种模式时遇到了一些问题,这反过来又产生了荒谬的输出。
让我从我的代码开始:
这是我的项目结构:
SampleWPFMVVMMediatorApp
|
|--Data
| |--MenuItems.xml
|
|--Extensions
| |--MediatorX
| | |--IColleague.cs
| | |--Mediator.cs
| | |--Messages.cs
| | |--MultiDictionary.cs
| |--ViewModelBase.cs
|
|--Models
| |--MenuItem.cs
|
|--ViewModels
| |--MainWindowViewModel.cs
| |--ParentMenuViewModel.cs
| |--ChildMenuViewModel.cs
| |--SamplePageViewModel.cs
|
|--Views
| |--ParentMenuView.xaml
| |--ChildMenuView.xaml
| |--SamplePage.xaml
|
|--App.xaml
|--MainWindow.xaml
代码:
我将只发布 ViewModel 和 Model 的代码以缩短问题的长度。
MenuItem.cs
public class MenuItem
{
public int Id { get; set; }
public string Name { get; set; }
}
MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
Mediator.Register(this, new[] { Messages.SelectedParentMenuItem, Messages.SelectedChildMenuItem });
}
private string _sourcePage;
public string SourcePage
{
get
{
return _sourcePage;
}
set
{
_sourcePage = value;
NotifyPropertyChanged("SourcePage");
}
}
private MenuItem _currentParentMenuItem;
public MenuItem CurrentParentMenuItem
{
get
{
return _currentParentMenuItem;
}
set
{
_currentParentMenuItem = value;
NotifyPropertyChanged("CurrentParentMenuItem");
}
}
private MenuItem _currentChildMenuItem;
public MenuItem CurrentChildMenuItem
{
get
{
return _currentChildMenuItem;
}
set
{
_currentChildMenuItem = value;
NotifyPropertyChanged("CurrentChildMenuItem");
if (CurrentChildMenuItem != null)
{
SourcePage = (from menuItem in XDocument.Load(Messages.DataDirectory + "MenuItems.xml")
.Element("MenuItems").Elements("MenuItem").Elements("MenuItem")
where (int)menuItem.Parent.Attribute("Id") == CurrentParentMenuItem.Id &&
(int)menuItem.Attribute("Id") == CurrentChildMenuItem.Id
select menuItem.Element("SourcePage").Value).FirstOrDefault();
}
}
}
public override void MessageNotification(string message, object args)
{
switch (message)
{
case Messages.SelectedParentMenuItem:
CurrentParentMenuItem = (MenuItem)args;
break;
case Messages.SelectedChildMenuItem:
CurrentChildMenuItem = (MenuItem)args;
break;
}
}
}
ParentMenuViewModel.cs
public class ParentMenuViewModel : ViewModelBase
{
public ParentMenuViewModel()
{
ParentMenuItems = new ObservableCollection<MenuItem>(
from menuItem in XDocument.Load(Messages.DataDirectory + "MenuItems.xml")
.Element("MenuItems").Elements("MenuItem")
select new MenuItem
{
Id = Convert.ToInt32(menuItem.Attribute("Id").Value),
Name = menuItem.Element("Name").Value
}
);
}
private ObservableCollection<MenuItem> _parentMenuItems;
public ObservableCollection<MenuItem> ParentMenuItems
{
get
{
return _parentMenuItems;
}
set
{
_parentMenuItems = value;
NotifyPropertyChanged("ParentMenuItems");
}
}
private MenuItem _selectedParentMenuItem;
public MenuItem SelectedParentMenuItem
{
get
{
return _selectedParentMenuItem;
}
set
{
_selectedParentMenuItem = value;
NotifyPropertyChanged("SelectedParentMenuItem");
Mediator.NotifyColleagues(Messages.SelectedParentMenuItem, SelectedParentMenuItem);
}
}
public override void MessageNotification(string message, object args)
{
throw new NotImplementedException();
}
}
ChildMenuViewModel.cs
public class ChildMenuViewModel : ViewModelBase
{
public ChildMenuViewModel()
{
Mediator.Register(this, new[] { Messages.SelectedParentMenuItem });
}
private MenuItem _currentParentMenuItem;
public MenuItem CurrentParentMenuItem
{
get
{
return _currentParentMenuItem;
}
set
{
_currentParentMenuItem = value;
NotifyPropertyChanged("CurrentParentMenuItem");
ChildMenuItemsOfSelectedParent
= new ObservableCollection<MenuItem>(
from menuItem in XDocument.Load(Messages.DataDirectory + "MenuItems.xml")
.Element("MenuItems").Elements("MenuItem").Elements("MenuItem")
where (int)menuItem.Parent.Attribute("Id") == CurrentParentMenuItem.Id
select new MenuItem
{
Id = Convert.ToInt32(menuItem.Attribute("Id").Value),
Name = menuItem.Element("Name").Value,
}
);
}
}
private ObservableCollection<MenuItem> _childMenuItemsOfSelectedParent;
public ObservableCollection<MenuItem> ChildMenuItemsOfSelectedParent
{
get
{
return _childMenuItemsOfSelectedParent;
}
set
{
_childMenuItemsOfSelectedParent = value;
NotifyPropertyChanged("ChildMenuItemsOfSelectedParent");
}
}
private MenuItem _selectedChildMenuItem;
public MenuItem SelectedChildMenuItem
{
get
{
return _selectedChildMenuItem;
}
set
{
_selectedChildMenuItem = value;
NotifyPropertyChanged("SelectedChildMenuItem");
Mediator.NotifyColleagues(Messages.SelectedChildMenuItem, SelectedChildMenuItem);
}
}
public override void MessageNotification(string message, object args)
{
switch (message)
{
case Messages.SelectedParentMenuItem:
CurrentParentMenuItem = (MenuItem)args;
break;
}
}
}
SamplePageViewModel.cs
public class SamplePageViewModel : ViewModelBase
{
public SamplePageViewModel()
{
Mediator.Register(this, new[] { Messages.SelectedChildMenuItem });
}
private MenuItem _currentChildMenuItem;
public MenuItem CurrentChildMenuItem
{
get
{
return _currentChildMenuItem;
}
set
{
_currentChildMenuItem = value;
NotifyPropertyChanged("CurrentChildMenuItem");
}
}
public override void MessageNotification(string message, object args)
{
switch (message)
{
case Messages.SelectedChildMenuItem:
CurrentChildMenuItem = (MenuItem)args;
break;
}
}
示例:
您可以下载我创建的示例项目 here .
问题:
请单击上行中提到的链接下载示例项目,以清楚地了解我的问题。
所以,我的问题是如何在另一个属性调用 NotifyColleagues 后通知一个注册自身的属性?
最佳答案
查找我的应用程序的更新版本 here .
<Rant>
对我来说,中介模式只是一种不必正确构建代码的方法,而且我从未在实际的代码场景中使用过它。您的演示应用程序是一个很好的示例,其中在 ViewModel 上创建子模型集合(例如 ObservableCollection<ChildMenuViewModel>
上 ParentMenuViewModel
)非常有意义。相比之下,从(甚至还不存在的)子 ViewModel 监视父 ViewModel 上的属性似乎就像搬起石头砸自己的脚。广播中的每个人都发出了刺耳的声音,而不是原本应该有的良好的等级制度。 </Rant>
.
如果您确实想保持在该模式内,则需要确保您的对象已注册到调解器(正如您在问题中已经注意到的那样),然后它才应该捕获调解器通知。
对于 Parent/ChildMenu,这很简单,只需重新排列 MainWindow.xaml:
<Grid Grid.Row="1">
<!-- ColumnDefinitions omitted -->
<views:ChildMenuView Grid.Column="0" />
<Frame Grid.Column="1" NavigationUIVisibility="Hidden" Content="{Binding SourcePage}"/>
</Grid>
<views:ParentMenuView Grid.Row="0" />
但是对于 Frame,情况要复杂得多,因为内容是动态实例化的(简化:通过在 SelectedChildMenuItem 的 setter 中设置 URI)。因此,您需要 BindingEngine 完成 URI 的更新,以便加载 Frame 内容,并且仅然后提高您的 NotifyColleagues(SelectedChildMenuItem)
称呼。这真的变得很难看...当然,一切都有一个解决方法,您可以通过更改框架设置、绑定(bind) Content
来规避最糟糕的情况。 (见上文)而不是 Source
并在调用 NotifyColleagues 之前实例化内容 ( SamplePage
):
private MenuItem _selectedChildMenuItem;
public MenuItem SelectedChildMenuItem
{
get { return _selectedChildMenuItem; }
set
{
_selectedChildMenuItem = value;
NotifyPropertyChanged("SelectedChildMenuItem");
LoadSourcePage(); // first instantiate the page (register it to mediator)
Mediator.NotifyColleagues(Messages.SelectedChildMenuItem, SelectedChildMenuItem); // only now notify
}
}
/// <summary>
/// Get the SourcePage and pass it to MainWindowViewModel
/// </summary>
private void LoadSourcePage()
{
if (SelectedChildMenuItem != null)
{
var sourceUri = (from menuItem in XDocument.Load(Messages.DataDirectory + "MenuItems.xml")
.Element("MenuItems").Elements("MenuItem").Elements("MenuItem")
where (int)menuItem.Parent.Attribute("Id") == CurrentParentMenuItem.Id &&
(int)menuItem.Attribute("Id") == SelectedChildMenuItem.Id
select menuItem.Element("SourcePage").Value).FirstOrDefault();
var relativePart = sourceUri.Substring(sourceUri.IndexOf(",,,") + 3);
var sourcePage = System.Windows.Application.LoadComponent(new Uri(relativePart, UriKind.Relative)); // instantiation with URI
Mediator.NotifyColleagues(Messages.SourcePage, sourcePage); // pass on
}
}
关于c# - MVVM + 中介模式 : Registration of Mediator occurs too late,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25901102/
我试图了解 ESB Mediation是,确切地说(具体例子),并且正在撞墙。 根据维基百科,数据中介重定向到 Data Transformation文章,唯一提到调解是模糊和神秘的: When th
我似乎有 admob 调解工作正常。我宁愿先使用 iAd,然后再使用 admob 填充。问题是我在 iTunes 连接中收到的 iAd 请求为零。我什至将百分比设置为 100%。我启用了它,一切都在
我有一个带有 ID、NAME、DATE 的 MySql 数据库我想通过使用 dblookup 介体来获取这些行,似乎不起作用,有人可以检查我的代理定义吗?
我正在尝试设置我的 Android 应用程序以显示来自中介网络的广告(顺便说一句,在任何地方都没有很好的解释),这是我到目前为止所做的: 1) 我已将发布商 ID 复制到将显示广告的 xml View
我的 AdMob 中介正在运行,它可以很好地提供 AdMob 广告,但是当我输入 MMedia 或 MobFox 的有效 ID 时,我收到请求,但填充数为 0。有谁知道这是为什么吗? 最佳答案 您还需
.h #import #import #import "GADBannerView.h" @interface MasterTableViewController : UITableViewCon
开门见山: 我了解什么是 mediationID 及其用途,但我无法在 admob 上获取 mediationID工具。 Mediation ad network guide看起来像这样: 但现实是我
我无法在 Android 应用程序中调解 admob 和 Facebook 受众网络 (FAN)。该应用仅转换来自 Admob 网络的广告。 Admob 和 FAN 之间的中介不起作用。以下是我遵循的
我目前在我的应用程序中使用 AdMob,我想集成 StartApp 但我想通过 AdMob 中介来管理它,有什么方法可以做到这一点(到目前为止我找不到任何文档,他们的支持也没有回答这个问题)? 最佳答
我正在尝试使用 InMobi 实现 AdMob 中介,但广告不会显示。我关注 their documentation我已经添加了 SDK 和 AndroidX: implementation 'com
有人知道如何使用 adMob 中介来管理 MMedia 的插页式广告吗? 我实际上使用 1) adMob Floor 2)MMedia(ID 横幅广告)3)admob“标准”。 想法? 在此先感谢您的
我想知道 Admob 中介的正确范例是什么。 到目前为止,我得到了一个普通的 AdView 横幅。 这就是它应该如何工作: onFailedToReceiveAd - 捕获此事件,这意味着 admob
背景 我们有一个相当复杂的 Silverlight 客户端,我们正在用 HTML/Javascript/CSS 重写它,构建在相同的 Web 服务之上。实际上,我们正在移植两个 Silverlight
是否有程序化方式来判断 AdMob 中介是展示 iAd 还是 AdMob 广告? 我的 GADBannerView 的父 View 必须根据正在展示的广告做一些特别的事情...... 最佳答案 您可以
我在使用 Applovin 和 Chartboost 实现 AdMob 奖励视频中介时被困了 3 天,代码完全找到了,但是当我启动应用程序时,它说“onRewardedVideoAdFailedToL
为此,我正在尝试将 iAds 集成到 Admob 中介 SDK 中,我从 Mediation website Download Link 下载了 iAdListAdapter并将其添加到我的 xcod
我是跟着Google的Admob/iAd mediation一步一步来的。我只会得到一个错误。这是确切的错误。我从 Xcode 复制并粘贴。 Ld /Users/RobShi/Desktop/Robf
我正在与多个第三方网络实现 AdMob 中介。我想测试这些网络中的每一个的调解是否得到很好的实现(广告很好地展示)。 我想强制显示来自定义网络的广告以测试其实现,然后快速切换到另一个网络。 执行此操作
我正在尝试通过 MoPub 调解 Facebook Audience Network,但我没有任何原生广告设置。我只想调解横幅广告和插页式广告。在 MoPub 文档中,没有关于横幅广告和插页式广告的说
假设我有一个 std::set , 我想知道它是否包含字符串 "name": #include #include using namespace std; bool has_name(const
我是一名优秀的程序员,十分优秀!