2

MVVM パターンを使用してビューとビューモデルを分離する既存の Silverlight アプリケーションのスイートがあります。IoC コンテナーに Unity 2.0 を使用して、依存関係を ViewModel クラス (およびサポートする型) に注入します。Unity コンテナーを使用して ViewModel を解決する既存の ViewModelLocator クラスがあります。

これらはすべて、実行時にうまく機能します。ただし、ViewModelLocator は、App.xaml.cs の Application_Start メソッドから「実行」される Bootstrapper クラスによって作成および構成されている Unity コンテナーに依存しているため、デザイナーまたは Blend でビューを開くことができなくなりました。 .

「ブレンダビリティ」をサポートするために ViewModelLocator を作り直す方法の提案を探しています。

Blendability のためだけに、ViewModel クラスにデフォルトのパラメーターなしのコンストラクターを強制的に実装するつもりはないことに注意してください。また、ViewModel に (MVVM Light ViewModelBase クラスの) IsInDesignMode プロパティをチェックさせて、サービス呼び出しではなくデザイン時のデータを提供するので、デザイン時と実行時に異なる ViewModel 実装がありません。

どう考えているか教えてください。

4

1 に答える 1

2

UI要素に優れた設計時エクスペリエンス(Blendを含む)を持たせる必要があります。それは合理的な目標のように聞こえます。

UI要素とは何かを見てみましょう。この回答の残りの部分では、これをコントロールと呼びます。コントロールの役割は、UIをレンダリングし、ユーザーイベントに応答することです。動作が必要な限り、UIレンダリングとユーザーイベントに関連する動作のみが必要です。

これに加えて、フレームワーク自体(SilverlightおよびWPF)はルールを課します。すべてのコントロールにはデフォルトのコンストラクターが必要です。さらに、DataContextはプロパティであるため、割り当てるのはオプションです。

カプセル化を念頭に置く必要があります。私たちが開発するコントロールは、上記の制約内でうまく機能するはずです。これは、デフォルトのコンストラクターがあることは別として、DataContextがなくても正しく機能するはずであることを意味します。つまり、Blendabilityエクスペリエンスは、を割り当てるためにブートストラップする必要のある外部コンテナーではなく、コントロール自体によって提供される必要がありますDataContext

コントロールがユーザーイベントに応答する必要がある場合、私は常にICommandインターフェイスが十分すぎると感じています。ICommandsコントロール内の該当するイベントハンドラーにアタッチします。はICommandsビューモデルによって定義されますが、の利点は、基本的にvoidメソッドであるということです。つまり、がnullICommandの場合に(no-op)ローカルデフォルトを指定するのは簡単です。DataContextただし、コマンドは設計者によって呼び出されないため、これが必要になることはめったにありません。


これが私の本の例です:

<Window x:Class="Ploeh.Samples.ProductManagement.WpfClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Product Management"
        Height="300"
        Width="300"
        MinHeight="300"
        MinWidth="300">
    <Window.Resources>
        <Style x:Key="ProductStyle" TargetType="{x:Type ListViewItem}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        </Style>
    </Window.Resources>
    <DockPanel FocusManager.FocusedElement="{Binding ElementName=productsListView}">
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <Separator />
                <MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
            </MenuItem>
            <MenuItem Header="_Actions">
                <MenuItem Header="_Refresh" InputGestureText="F5" Command="{Binding Path=RefreshCommand}" />
                <MenuItem Header="_Add Product" InputGestureText="Ins" Command="{Binding Path=InsertProductCommand}" />
                <MenuItem Header="_Edit Product" InputGestureText="Enter" Command="{Binding Path=EditProductCommand}" />
                <MenuItem Header="_Delete Product" InputGestureText="Del" Command="{Binding Path=DeleteProductCommand}" />
            </MenuItem>
        </Menu>
        <ToolBarTray DockPanel.Dock="Top" HorizontalAlignment="Stretch">
            <ToolBar HorizontalAlignment="Stretch" HorizontalContentAlignment="Left">
                <Button Command="{Binding Path=RefreshCommand}">Refresh</Button>
                <Button Command="{Binding Path=InsertProductCommand}">Add</Button>
                <Button Command="{Binding Path=EditProductCommand}">Edit</Button>
                <Button Command="{Binding Path=DeleteProductCommand}">Delete</Button>
            </ToolBar>
        </ToolBarTray>
        <ListView x:Name="productsListView" ItemContainerStyle="{StaticResource ProductStyle}" ItemsSource="{Binding Path=Products}" SelectionMode="Single">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" />
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" />
                    <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Path=UnitPrice}" />
                </GridView>
            </ListView.View>
        </ListView>
    </DockPanel>
</Window>

およびコードビハインド:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }
}
于 2011-09-01T07:14:47.973 に答える