15

私は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" のようなものを使用しました。それをメインビューとユーザーコントロール(MyControlView)に追加しようとしました。この件に関してご協力いただき、誠にありがとうございます。私はかなり行き詰まっており、本当にCaliburn.Microを使いたいです:)

よろしく、ダイヤモンドフィッシュ

編集:私はまだそれを動作させることができません.問題はブートストラップか何かにあるようです. ただし、明確にするために、テストプロジェクト用に実行しているコードを次に示します。

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

MyControlViewxaml:

<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 用であり、時々 CM ではなく Caliburn 用であるため、ブートストラッパーを間違って実装した可能性があります。このテスト プロジェクトでは、次のようになります: (App.xaml の .xaml-change を使用)

public class BootStrapper : Bootstrapper<MainViewModel>
{
}

ここで私を助けてください!それは私が見逃しているいくつかの基本的なもののようです:)

4

3 に答える 3

17

編集 - 以下の新しい(より完全な)回答:

わかりました、CM はあなたのために多くのことをしています。CM がそれを見つけられるようにクラスと xaml を準備することがすべてです。上で述べたように、私はフレームワークによる暗黙的なコードの仮定に頼るよりも、コードを明示的に書くことを好みます。

したがって、デフォルトの 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 または子ビューの 1 つ

<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 はブートストラップで、MainViewModel が指定されている行により開始点であることを確認しpublic class AppBootstrapper : Bootstrapper<MainViewModel>ます。and (およびその他の ViewModels) がそのコンストラクターにMainViewModel必要であるため、CM はそれぞれを構築する必要があります。これらの ViewModel はすべて最終的に IC に格納されます (後で作業がずっと簡単になります。これもまた別の議論になります)。YourFirstViewModelYourSecondViewModel

次のような行でバインドする VM を指定するため、CM はユーザーに代わって各ビューにデータコンテキストを割り当てます。cal:Bind.Model="Your.Namespace.ViewModels.YourFirstViewModel"

運が良ければ、それで始められるはずです。また、探しているものを正確に実行する CM サンプル プロジェクトも参照してくださいCaliburn.Micro.HelloEventAggregator(ただし、Event Aggregator のデモとして説明されていますが、これも非常に便利ですが、別の議論です)。

(以下の畏敬の念に対する元の回答)

これを行う必要があります:

<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 UserControls などをネストする必要がない場合でも、実際にはこの方法を好みます。ビューがバインドされているウィッチ VM を明示的に宣言する (それでも CM に IoC でのすべての面倒な作業を処理させる) ことを、暗黙のコードから cm に "理解させる" よりも優先します。

優れたフレームワークを使用しても、明示的なコードは暗示的なコードよりも保守が容易です。バインドされたビュー モデルを指定すると、期待されるデータ コンテキストが明確になるという利点があるため、後で推測する必要がなくなります。

于 2011-10-24T18:15:17.313 に答える
17

より良いアプローチは、メイン ビューで使用し、タイプがContentControlのパブリック プロパティと同じ名前を付けることです。例えばMainViewModelMyControlViewModel

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(...); }
}
于 2011-10-24T19:44:08.257 に答える
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
}
于 2013-04-04T12:42:08.030 に答える