3

それが悪いデザインであることは知っていますが、ビューモデルからビューにアクセスする必要があります。これは、バインドをサポートしておらず、コードで入力する必要がある古いコントロール(Winformsコントロールなど)があるためです。

私はAvalonDock2.0のMVVMモデルを使用しており、次のようなものがあります。

   <ad:DockingManager x:Name="dockManager" 
                  DocumentsSource="{Binding Files}"
                  AnchorablesSource="{Binding Tools}"
        ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}">
        <ad:DockingManager.LayoutItemTemplateSelector>
            <local:PanesTemplateSelector>
                <local:PanesTemplateSelector.NavigationViewTemplate>
                    <DataTemplate>
                        <tvext:TreeViewExtended />
                    </DataTemplate>
                </local:PanesTemplateSelector.NavigationViewTemplate>
            </local:PanesTemplateSelector>
        </ad:DockingManager.LayoutItemTemplateSelector>

したがって、テンプレートNavigationViewTemplateは、コレクションToolsの1つのアイテムにバインドされます。これは、NavigationViewModelタイプの私のViewModelです。

たとえば、TextBoxをビューモデルのプロパティにバインドするのに問題はありません。しかし、NavigationViewModelからテンプレート内のtvext:TreeViewExtendedコントロールにアクセスして、テンプレートを埋める方法がわかりません。

TIAマイケル

4

3 に答える 3

7

ええ、私はViewModelにビューについて知らせるのが好きではありませんが、あなたが尋ねたので、ここに1つのアイデアがあります:

 1. Create an interface for your View (if you haven't already) and add whatever functionality to that interface that you need access to from the ViewModel. Lets call it ISomeView
 2. add/implement the interface on the View
 3. add property to the ViewModel ISomeView View {get;set;} 
 4. in the view depending where the ViewModel is being injected assign populate the ViewModel's property, for example you can do it on DataContextChanged:

    private void OnDataContextChanged (object sender, ...EventArgs e)
    {
         // making up your ViewModel's name as ISomeViewModel
         ((ISomeViewModel)sender).View = this;
     }
于 2012-06-28T15:33:20.367 に答える
4

ビューモデルでイベントを作成し、ビューでこれらのイベントをサブスクライブするだけなので、ビューとビューモデルはまだ強力に結合されておらず、必要なものを取得できます。

于 2012-06-29T05:47:48.250 に答える
3

ViewModelからWinformsコントロールにアクセスしないことをお勧めします。ビューに関連するすべてのものをビューに保持します。これは次のように実行できます。

  1. 名前付きなどのWPFカスタムコントロールを作成しますTreeViewExtendedWrapper。(カスタムWPFコントロールを作成する方法の短いチュートリアルについては、この記事を参照してください)。

  2. カスタムコントロールのコントロールテンプレート内(Themes \ Generic.xamlファイル内)に、Winformsコントロールを配置します。

    <ControlTemplate TargetType="{x:Type local:TreeViewExtendedWrapper}">
        <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}">
            <tvext:TreeViewExtended />
        </Border>
    </ControlTemplate>
    
  3. ViewModelにバインドする必要があるすべてのWinformsコントロールプロパティのカスタムコントロールに依存関係プロパティを追加します。

  4. また、ビューモデルにバインドする必要があるすべてのコマンドのカスタムコントロールに依存関係プロパティを追加します。

  5. カスタムコントロールのコードビハインド内にC#コードを記述して、カスタムコントロールの依存関係プロパティを、Winformsコントロールのプロパティ、イベント、およびメソッドに接続します。

  6. データテンプレート内に、必要なデータバインディングを使用してカスタムコントロールを配置します。

    <DataTemplate>
        <local:TreeViewExtendedWrapper MyProperty={Binding MyProperty}/> 
    </DataTemplate> 
    

このアプローチでは、データバインディングを使用して、ViewModelとWinformsコントロールを接続できます。つまり、MVVMの原則に違反しません。

于 2012-06-28T14:41:06.473 に答える