2011-10-24 60 views
12

我正在嘗試使用WPF使用Caliburn.Micro。我如何在視圖中添加多個視圖?使用WPF和Caliburn.Micro在視圖中添加多個視圖

<Window x:Class="ProjectName.Views.MainView" 
     ...> 
<Grid> 
     <views:MyControlView /> 
</Grid> 
</Window> 

另一種觀點,與視圖模型:MyControlViewModel

<UserControl x:Class="ProjectName.Views.MyControlView" 
     ...> 
<Grid> 
    ... 
</Grid> 
</UserControl> 

如果我剛纔添加的視圖,它不會檢測到它與相應名稱的視圖模型。我如何將它綁定到它?

我試過了不同的引導程序,並使用類似cal:Bind.Model =「path/classname/merge of the two」。試圖將其添加到mainview和usercontrol(MyControlView)。我非常感謝有關此事的任何幫助。我非常堅持,我真的想用Caliburn.Micro :)

最好的問候, diamondfish

編輯:我仍然無法得到它的工作,這個問題似乎是在引導程序或其他東西。但只是爲了澄清,這裏是我正在運行的測試項目的代碼。

的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-參考:

xmlns:cal="http://www.caliburnproject.org" 

我的項目http://clip2net.com/s/1gthM

由於文檔的屏幕截圖大多是Silverlight的,有時是卡利而不是CM,我可能已經實現了引導程序錯誤。對於這個測試項目,就像這樣:(使用App.xaml中的.xaml-change)

public class BootStrapper : Bootstrapper<MainViewModel> 
{ 
} 

請幫我看看這裏!現在看來似乎是我失蹤:)一些基本的東西

+0

- 編輯帖子包含MVVM標籤,歡迎來到SO! – EtherDragon

+0

檢查anser - 我添加了一個關於導出類型的部分。這是c.m找到與視圖相關的ViewModel的重要條件。 – EtherDragon

回答

16

編輯 - 新(更完整)回答以下:

好吧,CM是做了很多的東西對你來說,它是所有關於讓你的類並且xaml爲CM準備好能夠找到它。如上所述,我更願意寫代碼顯式,而不是依賴框架的隱式代碼假設。

因此,默認C.M項目中的Bootstrapper就好了。

public class AppBootstrapper : Bootstrapper<MainViewModel> 
{ 
    // ... You shouldn't need to change much, if anything 
} 

的部分'引導程序」是非常重要的,是它表明該視圖模型是你的第一個,或主屏幕上,當應用程序啓動。

[Export(Typeof(MainViewModel))] 
public class MainViewModel : Screen, IShell 
{ 
    [ImportingConstructor] 
    public MainViewModel(YourFirstViewModel firstViewModel, YourSecondViewModel secondviewModel) // etc, for each child ViewModel 
    { 
    } 
} 

[ImportingConstructor]你不需要做以外的任何其他指定的MainViewModel需要其他的ViewModels的存在。在我的情況下,我喜歡我的MainViewModel是一個容器,只有容器,事件邏輯在別處處理。但是,您可以輕鬆地在此處理您的處理邏輯 - 但這是其他討論。

現在每個孩子的視圖模型也需要導出它們自己,所以C.M知道在哪裏可以找到它們。

[Export(Typeof(YourFirstViewModel))] 
public class YourFirstViewModel : IShell 
{ 
    // VM properties and events here 
} 

如果您只是使用默認構造函數,則無需指定Importing構造函數。

現在,您的每一個意見,這些都將是這個樣子:

<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> 

一個到底是什麼竟然會在這裏?

那麼,C.M在引導程序中看到,由於指定public class AppBootstrapper : Bootstrapper<MainViewModel>的行,MainViewModel是起點。 MainViewModel要求在其構造函數中需要YourFirstViewModelYourSecondViewModel(以及其他ViewModels),所以C.M構造每個構造函數。所有這些ViewModel最終都在IoC中(以後讓你的生活變得更加容易 - 再次,是另一個討論)。

C.M手柄分配的datacontext,以您的名義,給每一個觀點,因爲你指定虛擬機與線綁定到像cal:Bind.Model="Your.Namespace.ViewModels.YourFirstViewModel"

運氣好的話,應該讓你開始。還請參考CM示例項目Caliburn.Micro.HelloEventAggregator,因爲它確實如你所期望的那樣(儘管它被描述爲Event Aggregator演示,這也是非常有用的 - 但是,再次討論)

(Original Answer for reverence,以下)

你需要這樣做:

<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"

不要忘記導出你的類類型,否則c.m找不到它。

[Export(typeof(YourViewModel))] 
public class YourViewModel : IShell 
{ 
    ... 
} 

然後,您可以嵌套您認爲合適的用戶控件。這是使用C.M的一種非常好的方法,您會發現它具有高度的可擴展性。唯一的弱點是View和ViewModel必須在同一個項目中(據我所知)。但是這種方法的優點是,如果你願意的話,你可以將視圖和視圖模型類分離到不同的命名空間中(在同一個項目中),以保持組織性。

作爲對c.m的評論,我更喜歡這種方法,實際上,即使我不必嵌套查看UserControls等。我寧願明確地聲明一個View綁定到的VM(並且讓C.M處理IoC中所有的繁重工作),而不是讓c.m「從隱含的代碼中」弄清楚它。

即使有一個好的框架:顯式代碼比隱含代碼更易維護。指定綁定視圖模型的好處是可以清楚地說明您的數據上下文應該是什麼,因此您不需要稍後再猜測。

+0

謝謝你指出它應該如何。 Alhough,我無法讓它工作。請查看我的原始帖子並檢查更新的部分。希望得到這個修正:) – diamondfish

+1

你在正確的軌道上 - 我們只是錯過了一些愚蠢的東西。增加了導出信息。 – EtherDragon

+0

Gah,它不會工作:S我嘗試添加一個MefBootstrapper類並實現了IShell接口,但仍然沒有任何結果。如果你有時間檢查我的項目,請隨時這樣做:) http://johanbjarnle.se/temp/CaliburnTest.rar – diamondfish

16

更好的方法是在您的主視圖上使用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(...); } 
} 
+0

我得到了這個工作。但它似乎並沒有像C.M一樣使用?雖然這樣做的好方法,非常感謝! – diamondfish

+0

我還發現在使用ContentControl時在VS中編輯時無法在MainView中看到MyControl的界面。有沒有辦法做到這一點? – diamondfish

+2

您正在使用CM,即將ContentControl的名稱與視圖模型屬性的名稱相匹配,查找視圖,將視圖注入ContentControl並將該視圖的控件綁定到視圖模型屬性。這將是與Caliburn.Micro查看構圖的推薦方法。 – devdigital

1

在文件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 
} 
+0

修復了我的值在使用Ninject引導程序時不能爲空的錯誤。非常感謝 :) – Dave

相關問題