[英]Add multiple views inside a view using WPF and Caliburn.Micro
我正在嘗試使用帶有WPF的Caliburn.Micro學習。 如何在視圖中添加多個視圖?
<Window x:Class="ProjectName.Views.MainView"
...>
<Grid>
<views:MyControlView />
</Grid>
</Window>
另一個視圖,使用viewmodel:MyControlViewModel
<UserControl x:Class="ProjectName.Views.MyControlView"
...>
<Grid>
...
</Grid>
</UserControl>
如果我只是添加視圖,它將不會檢測到它具有具有適當名稱的viewmodel。 我怎么能把它綁在上面呢?
我已嘗試使用不同的bootstrappers並使用類似cal:Bind.Model =“path / classname / merge of the two”。 試圖將其添加到主視圖和usercontrol(MyControlView)。 我非常感謝有關此事的任何幫助。 我幾乎卡住了,我真的想用Caliburn.Micro :)
最好的問候,鑽石魚
編輯:我仍然無法讓它工作,問題似乎是在引導程序或其他東西。 但只是為了澄清,這是我的代碼,我正在運行testproject。
MainView xaml:
<Window x:Class="Test.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
xmlns:views="clr-namespace:Test.Views"
Title="MainWindow" Height="360" Width="640">
<Grid>
<views:MyControlView />
</Grid>
MainViewModel代碼:
public partial class MainViewModel : PropertyChangedBase
{
}
MyControlView xaml:
<UserControl x:Class="Test.Views.MyControlView"
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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
cal:Bind.Model="Test.MyControlViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding MyProp}"/>
</Grid>
MyControlView代碼:
public class MyControlViewModel : PropertyChangedBase
{
public string MyProp
{
get { return "Working"; }
}
}
錯誤的屏幕截圖: http : //clip2net.com/s/1gtgt
我試過了
cal:Bind.Model="Test.ViewModels.MyControlViewModel"
同樣。 還嘗試了cal-reference:
xmlns:cal="http://www.caliburnproject.org"
我的項目http://clip2net.com/s/1gthM的屏幕截圖
由於文檔主要用於silverlight,有時用於Caliburn而不是CM,我可能已經錯誤地實現了bootstrapper。 對於這個測試項目,它就像這樣:(在App.xaml中使用.xaml-change)
public class BootStrapper : Bootstrapper<MainViewModel>
{
}
請幫幫我吧! 好像這是我缺少的一些基本內容:)
編輯 - 新(更完整)答案如下:
好的,CM正在為你做很多事情,這都是為了讓你的類和xaml為CM准備好找到它。 如上所述,我更喜歡將代碼顯式化,而不是依賴於框架的隱式代碼假設。
所以,來自默認CM項目的Bootstrapper就好了。
public class AppBootstrapper : Bootstrapper<MainViewModel>
{
// ... You shouldn't need to change much, if anything
}
“Bootstrapper”部分非常重要,它指示應用程序啟動時哪個ViewModel是您的第一個或主屏幕。
[Export(Typeof(MainViewModel))]
public class MainViewModel : Screen, IShell
{
[ImportingConstructor]
public MainViewModel(YourFirstViewModel firstViewModel, YourSecondViewModel secondviewModel) // etc, for each child ViewModel
{
}
}
在[ImportingConstructor]
,除了指定MainViewModel需要存在其他ViewModel之外,您不需要執行任何操作。 在我的特定情況下,我喜歡我的MainViewModel是一個容器,只有容器,事件邏輯在別處處理。 但你可以很容易地在這里使用你的Handle邏輯 - 但這是其他一些討論。
現在每個子視圖模型也需要自己導出,因此CM知道在哪里找到它們。
[Export(Typeof(YourFirstViewModel))]
public class YourFirstViewModel : IShell
{
// VM properties and events here
}
如果您只是使用默認構造函數,則無需指定導入構造函數。
現在,您對這些視圖的每個視圖將如下所示:
<UserControl x:Class="Your.Namespace.MainView"
xmlns:views="clr-namespace:Your.Namespace.Views"
xmlns:cal="http://www.caliburnproject.org"
cal:Bind.Model="Your.Namespace.ViewModels.MainViewModel"
MinWidth="800" MinHeight="600">
<StackPanel x:Name="RootVisual">
<views:YourFirstView />
<views:YourSecondView />
<!-- other controls as needed -->
</StackPanel>
</UserControl>
XAMl或其中一個子視圖
<UserControl x:Class="Your.Namespace.Views.YourFirstView"
xmlns:cal="http://www.caliburnproject.org"
cal:Bind.Model="Your.Namespace.ViewModels.YourFirstViewModel"
MinWidth="800" MinHeight="600">
<Grid x:Name="RootVisual">
<!-- A bunch of controls here -->
</Grid>
</UserControl>
到底是怎么回事?
好吧,CM在引導程序中看到,由於指定public class AppBootstrapper : Bootstrapper<MainViewModel>
的行,MainViewModel是起點。 MainViewModel
要求在其構造函數中需要YourFirstViewModel
和YourSecondViewModel
(以及其他ViewModel),因此CM構造每個。 所有這些ViewModel最終都會出現在IoC中(以后會讓您的生活變得更輕松 - 再次,整個其他討論)。
CM處理代表您為每個視圖分配datacontext,因為您指定要綁定到哪個VM的行如cal:Bind.Model="Your.Namespace.ViewModels.YourFirstViewModel"
運氣好的話,應該讓你開始吧。 另請參閱CM示例項目Caliburn.Micro.HelloEventAggregator
因為它完全符合您的要求(雖然,它被描述為事件聚合器演示,這也非常有用 - 但同樣,另一個討論)
(尊敬的原始答案,見下文)
你需要這樣做:
<UserControl x:Class="Your.Namespace.Here.YourView"
xmlns:cal="http://www.caliburnproject.org"
cal:Bind.Model="Your.Namespace.Here.YourViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="1024">
<YourControlLayout />
</UserControl>
注意行cal:Bind.Model="Your.Namespace.Here.YourViewModel"
,它指定將此視圖綁定到的確切視圖模型。
不要忘記導出您的類類型,否則cm無法找到它。
[Export(typeof(YourViewModel))]
public class YourViewModel : IShell
{
...
}
然后,您可以根據需要嵌套用戶控件。 這是一種使用CM的非常好的方法,你會發現它具有高度的可擴展性。 唯一的缺點是View和ViewModel必須在同一個項目中(據我所知)。 但是這種方法的優點是,如果您願意,可以將View和View Model類分離到不同的命名空間(在同一個項目中),以保持組織有序。
作為對cm的評論,我更喜歡這種方法,實際上,即使我不需要嵌套View UserControl等。 我寧願明確地聲明一個View被綁定的女巫VM(並且仍然允許CM處理IoC中所有繁重的工作),而不是讓cm從隱含代碼中“弄明白”。
即使有一個好的框架:顯式代碼比隱含代碼更易於維護。 指定綁定的視圖模型的好處是可以清楚地說明您的數據上下文是什么,因此您不需要稍后猜測。
更好的方法是在主視圖上使用ContentControl
,並在MainViewModel
為其提供與MyControlViewModel
類型相同的公共屬性。 例如
MainView.xaml
<ContentControl x:Name="MyControlViewModel" />
MainViewModel.cs
// Constructor
public MainViewModel()
{
// It would be better to use dependency injection here
this.MyControlViewModel = new MyControlViewModel();
}
public MyControlViewModel MyControlViewModel
{
get { return this.myControlViewModel; }
set { this.myControlViewModel = value; this.NotifyOfPropertyChanged(...); }
}
在文件App.xaml.cs中,在方法GetInstance中添加以下行
protected override object GetInstance(Type service, string key) { if (service == null && !string.IsNullOrWhiteSpace(key)) { service = Type.GetType(key); key = null; } // the rest of method }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.