Caliburn.Micro と Modern UI ( https://mui.codeplex.com ) を使用してプロジェクトを開始しましたが、ビュー モデルで IContent のナビゲーション イベントを発生させるのに苦労しています。私はすでに2つを接続して、次のように相互に連携させています。
CM ブートストラップ:
public class CMBootstrapper : Bootstrapper<IShell> {
private CompositionContainer container;
private DirectoryCatalog catalog;
public CMBootstrapper() { }
protected override void Configure() {
catalog = new DirectoryCatalog(".", "*.*");
container = new CompositionContainer(catalog);
var compositionBatch = new CompositionBatch();
compositionBatch.AddExportedValue<IWindowManager>(new WindowManager());
compositionBatch.AddExportedValue<IEventAggregator>(new EventAggregator());
compositionBatch.AddExportedValue(container);
container.Compose(compositionBatch);
}
protected override IEnumerable<Assembly> SelectAssemblies() {
List<Assembly> assemblies = new List<Assembly>();
assemblies.Add(Assembly.GetExecutingAssembly());
return assemblies;
}
protected override object GetInstance(Type serviceType, string key) {
string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = container.GetExportedValues<object>(contract);
if (exports.Count() > 0)
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
protected override IEnumerable<object> GetAllInstances(Type serviceType) {
return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
protected override void BuildUp(object instance) {
container.SatisfyImportsOnce(instance);
}
}
モダン UI コンテンツ ローダー:
[Export]
public class MuiContentLoader : DefaultContentLoader {
protected override object LoadContent(Uri uri) {
var content = base.LoadContent(uri);
if (content == null)
return null;
// Locate VM
var viewModel = ViewModelLocator.LocateForView(content);
if (viewModel == null)
return content;
// Bind VM
if (content is DependencyObject)
ViewModelBinder.Bind(viewModel, content as DependencyObject, null);
return content;
}
}
MuiView.xaml (シェル)
<mui:ModernWindow x:Class="XMOperations.Views.MuiView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
ContentLoader="{StaticResource ModernContentLoader}"
d:DesignHeight="300" d:DesignWidth="300">
<mui:ModernWindow.TitleLinks>
<mui:Link DisplayName="Settings" Source="/Views/SettingsView.xaml" />
</mui:ModernWindow.TitleLinks>
<mui:ModernWindow.MenuLinkGroups>
<mui:LinkGroupCollection>
<mui:LinkGroup GroupName="Hello" DisplayName="Hello">
<mui:LinkGroup.Links>
<mui:Link Source="/Views/ChildView.xaml" DisplayName="Click me"></mui:Link>
</mui:LinkGroup.Links>
</mui:LinkGroup>
</mui:LinkGroupCollection>
</mui:ModernWindow.MenuLinkGroups>
MuiViewModel
[Export(typeof(IShell))]
public class MuiViewModel : Conductor<IScreen>.Collection.OneActive, IShell {
}
各子ビューがエクスポートされ、次のように IContent が実装されます。
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class SettingsViewModel : Screen, IContent {
#region IContent Implementation
public void OnFragmentNavigation(FragmentNavigationEventArgs e) {
Console.WriteLine("SettingsViewModel.OnFragmentNavigation");
}
public void OnNavigatedFrom(NavigationEventArgs e) {
Console.WriteLine("SettingsViewModel.OnNavigatedFrom");
}
public void OnNavigatedTo(NavigationEventArgs e) {
Console.WriteLine("SettingsViewModel.OnNavigatedTo");
}
public void OnNavigatingFrom(NavigatingCancelEventArgs e) {
Console.WriteLine("SettingsViewModel.OnNavigatingFrom");
}
#endregion
}
しかし、それらのどれも発砲していませんでした。いくつかのデバッグの後、イベントModernFrame
をチェックしていることがわかった. そこで、ViewModel にイベントを渡すためにカスタム UserControl クラスを作成しました。(SettingsView as IContent)
UserControl
MuiContentControl
public delegate void FragmentNavigationEventHandler(object sender, FragmentNavigationEventArgs e);
public delegate void NavigatedFromEventHandler(object sender, NavigationEventArgs e);
public delegate void NavigatedToEventHandler(object sender, NavigationEventArgs e);
public delegate void NavigatingFromEventHandler(object sender, NavigatingCancelEventArgs e);
public class MuiContentControl : UserControl, IContent {
public event FragmentNavigationEventHandler FragmentNavigation;
public event NavigatedFromEventHandler NavigatedFrom;
public event NavigatedToEventHandler NavigatedTo;
public event NavigatingFromEventHandler NavigatingFrom;
public MuiContentControl() : base() {
}
public void OnFragmentNavigation(FragmentNavigationEventArgs e) {
if(FragmentNavigation != null)
FragmentNavigation(this, e);
}
public void OnNavigatedFrom(NavigationEventArgs e) {
if (NavigatedFrom != null)
NavigatedFrom(this, e);
}
public void OnNavigatedTo(NavigationEventArgs e) {
if(NavigatedTo != null)
NavigatedTo(this, e);
}
public void OnNavigatingFrom(NavigatingCancelEventArgs e) {
if(NavigatingFrom != null)
NavigatingFrom(this, e);
}
}
次に、Message.Attach でイベントをリッスンするようにビューを変更しました。
設定ビュー
<local:MuiContentControl x:Class="XMOperations.Views.SettingsView"
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:mui="http://firstfloorsoftware.com/ModernUI"
xmlns:cal="http://www.caliburnproject.org"
xmlns:local="clr-namespace:XMOperations"
cal:Message.Attach="[Event FragmentNavigation] = [Action OnFragmentNavigation($source, $eventArgs)];
[Event NavigatedFrom] = [Action OnNavigatedFrom($source, $eventArgs)];
[Event NavigatedTo] = [Action OnNavigatedTo($source, $eventArgs)];
[Event NavigatingFrom] = [Action OnNavigatingFrom($source, $eventArgs)]"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Style="{StaticResource ContentRoot}">
<mui:ModernTab SelectedSource="/Views/Settings/AppearanceView.xaml" Layout="List" ContentLoader="{StaticResource ModernContentLoader}">
<mui:ModernTab.Links>
<mui:Link DisplayName="Appearance" Source="/Views/Settings/AppearanceView.xaml" />
</mui:ModernTab.Links>
</mui:ModernTab>
</Grid>
発生しない唯一のイベントは NavigatedTo であるため、イベントがディスパッチされるまで Message.Attach は適用されないと思います。私はおそらくこれを非常に間違った方法で行っており、大規模な再構築を受け入れています。