WPF Caliburn 集成 - 交互问题
WPF Caliburn integration - Interaction issue
我正在开发 WPF 应用程序,我想集成 Caliburn Micro。
在主页面中,我有一个内容展示器,它在应用程序启动时加载了一个 UserControl(假设名为 MenuView,如下所示)。但是当我尝试在 MenuView 中使用交互处理 MouseDown 事件时,该方法从未在 MenuViewModel 中调用,因为可能视图模型未在 Caliburn 中注册。
这是应用程序结构:
主视图模型:
public class MainViewModel : PropertyChangedBase, IShell
{
public MainViewModel()
{
SelectedView = new MenuView();
}
private UserControl _selectedView;
public UserControl SelectedView
{
get { return _selectedView; }
set
{
_selectedView = value;
NotifyOfPropertyChange();
}
}
}
主视图:
<Window x:Class="UITablet.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" WindowState="Maximized" WindowStyle="ThreeDBorderWindow">
<StackPanel VerticalAlignment="Bottom">
<ContentPresenter Content="{Binding SelectedView, Mode=TwoWay}" />
</StackPanel>
</Window>
菜单视图模型:
public class MenuViewModel : IShell
{
public void RedirectToSapAction()
{
//...
}
}
菜单视图:
<UserControl x:Class="UI.Tablet.Views.MenuView"
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"
mc:Ignorable="d"
xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button x:Name="TestButton" Width="100" Height="20" Content="Click me!">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cal:ActionMessage MethodName="RedirectToSapAction" >
</cal:ActionMessage >
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</UserControl>
最后是 AppBootstrapper
using System.IO;
using System.Linq;
using System.Reflection;
using WpfApplication1.ViewModels;
using System;
using System.Collections.Generic;
using Caliburn.Micro;
namespace WpfApplication1
{
public class AppBootstrapper : BootstrapperBase
{
SimpleContainer container;
public AppBootstrapper()
{
Initialize();
}
protected override void Configure()
{
ViewLocator.AddSubNamespaceMapping("WpfApplication1.ViewModels", "UITablet.Views");
container = new SimpleContainer();
container.Singleton<IWindowManager, WindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<IShell, MainViewModel>();
}
protected override object GetInstance(Type service, string key) {
var instance = container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service) {
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance) {
container.BuildUp(instance);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) {
DisplayRootViewFor<IShell>();
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
var assemblies = new List<Assembly>();
assemblies.AddRange(base.SelectAssemblies());
//Load new ViewModels here
string[] fileEntries = Directory.GetFiles(Directory.GetCurrentDirectory());
assemblies.AddRange(from fileName in fileEntries where fileName.Contains("UITablet.dll") select Assembly.LoadFile(fileName));
return assemblies;
}
}
}
如您所见,视图被放置在一个单独的项目中,并且我做了一些技巧以使 Caliburn 正常运行。
问题是,这种分离是什么问题?还是我遗漏了什么?
在您的主视图模型中,定义类型为 MenuViewModel
的 属性
private MenuViewModel_selectedView;
public MenuViewModel SelectedView
{
get { return _selectedView; }
set
{
_selectedView = value;
NotifyOfPropertyChange();
}
}
您可以在构造函数中或任何需要的时候实例化 SelectedView
属性。
在您看来:
<ContentPresenter cal:View.Model="{Binding SelectedView, Mode=TwoWay}">
</ContentPresenter>
我正在开发 WPF 应用程序,我想集成 Caliburn Micro。 在主页面中,我有一个内容展示器,它在应用程序启动时加载了一个 UserControl(假设名为 MenuView,如下所示)。但是当我尝试在 MenuView 中使用交互处理 MouseDown 事件时,该方法从未在 MenuViewModel 中调用,因为可能视图模型未在 Caliburn 中注册。
这是应用程序结构:
主视图模型:
public class MainViewModel : PropertyChangedBase, IShell
{
public MainViewModel()
{
SelectedView = new MenuView();
}
private UserControl _selectedView;
public UserControl SelectedView
{
get { return _selectedView; }
set
{
_selectedView = value;
NotifyOfPropertyChange();
}
}
}
主视图:
<Window x:Class="UITablet.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" WindowState="Maximized" WindowStyle="ThreeDBorderWindow">
<StackPanel VerticalAlignment="Bottom">
<ContentPresenter Content="{Binding SelectedView, Mode=TwoWay}" />
</StackPanel>
</Window>
菜单视图模型:
public class MenuViewModel : IShell
{
public void RedirectToSapAction()
{
//...
}
}
菜单视图:
<UserControl x:Class="UI.Tablet.Views.MenuView"
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"
mc:Ignorable="d"
xmlns:cal="http://www.caliburnproject.org"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button x:Name="TestButton" Width="100" Height="20" Content="Click me!">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cal:ActionMessage MethodName="RedirectToSapAction" >
</cal:ActionMessage >
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</UserControl>
最后是 AppBootstrapper
using System.IO;
using System.Linq;
using System.Reflection;
using WpfApplication1.ViewModels;
using System;
using System.Collections.Generic;
using Caliburn.Micro;
namespace WpfApplication1
{
public class AppBootstrapper : BootstrapperBase
{
SimpleContainer container;
public AppBootstrapper()
{
Initialize();
}
protected override void Configure()
{
ViewLocator.AddSubNamespaceMapping("WpfApplication1.ViewModels", "UITablet.Views");
container = new SimpleContainer();
container.Singleton<IWindowManager, WindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<IShell, MainViewModel>();
}
protected override object GetInstance(Type service, string key) {
var instance = container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service) {
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance) {
container.BuildUp(instance);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) {
DisplayRootViewFor<IShell>();
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
var assemblies = new List<Assembly>();
assemblies.AddRange(base.SelectAssemblies());
//Load new ViewModels here
string[] fileEntries = Directory.GetFiles(Directory.GetCurrentDirectory());
assemblies.AddRange(from fileName in fileEntries where fileName.Contains("UITablet.dll") select Assembly.LoadFile(fileName));
return assemblies;
}
}
}
如您所见,视图被放置在一个单独的项目中,并且我做了一些技巧以使 Caliburn 正常运行。 问题是,这种分离是什么问题?还是我遗漏了什么?
在您的主视图模型中,定义类型为 MenuViewModel
private MenuViewModel_selectedView;
public MenuViewModel SelectedView
{
get { return _selectedView; }
set
{
_selectedView = value;
NotifyOfPropertyChange();
}
}
您可以在构造函数中或任何需要的时候实例化 SelectedView
属性。
在您看来:
<ContentPresenter cal:View.Model="{Binding SelectedView, Mode=TwoWay}">
</ContentPresenter>