2

私は何日も検索して試してみましたが、最終的にここで質問する必要があります. メインビューでビューを動的に切り替えられるようにしたい、MVVM Light を使用した Silverlight 5 アプリケーションがあります。

簡単にするために、2 つのボタンがあるとします。

Button1 が TestView1 に切り替わります。

Button2 は TestView2 に切り替わります。

 <Button Content="TestView1" Grid.Column="1" Command="{Binding CallTestView1Command}" HorizontalAlignment="Left" Margin="185,17,0,0" VerticalAlignment="Top" Width="75"/>
    <Button Content="TestView2" Grid.Column="1" Command="{Binding CallTestView2Command}" HorizontalAlignment="Left" Margin="280,17,0,0" VerticalAlignment="Top" Width="75"/>

私が行った方法は、リレーコマンドをボタンにバインドし、対応するビューの新しいビューモデルをインスタンス化することです。すなわち:

private RelayCommand _callTestView1Command;
    public RelayCommand CallTestView1Command
    {
        get
        {
            return _callTestView1Command ??
                   (_callTestView1Command = new RelayCommand(() =>
                       {
                           CurrentView = ViewModelLocator.NinjectKernel.Get<TestViewModel1>();
                       }));
        }
    }

次に、CurrentViewmodel が新しいビューモデルに設定されます。MainView で、CurrentView を ContentControl にバインドしました。

<Border x:Name="displayedView" Grid.Row="2">
        <ContentControl Content="{Binding CurrentView}" />
    </Border>

CurrentView は変更されますが、ビューのコンテンツを実際に表示する代わりに、インスタンス化された ViewModel の名前空間を表示するだけなので、これは実際にはある程度機能します。

これまでのところ、主に次の情報源から得た知識を使用してきました。

http://rachel53461.wordpress.com/2011/05/28/switching-between-viewsusercontrols-using-mvvm/

ビューを ContentControl にロードし、ボタンをクリックしてプロパティを変更する

しかし、それらは私の問題を解決しないか、実際にビューを表示する方法をよく理解していません.:-(

GalaSoft の MVVM Light を使用して、Silverlight 5 でビューを正しく切り替える方法について、適切な説明がある人はいますか。

ありがとう

4

4 に答える 4

2

欠けている部分はDataTemplates、ViewModels をレンダリングする方法を WPF に伝えることです

<Window.Resources>
    <DataTemplate TargetType="{x:Type local:TestViewModel1}">
        <local:TestView1 />
    </DataTemplate>

    <DataTemplate TargetType="{x:Type local:TestViewModel2}">
        <local:TestView2 />
    </DataTemplate>
</Window.Resources>

ViewModelオブジェクトを に配置するなど、ビジュアル ツリーにオブジェクトを挿入すると、オブジェクトのへのバインドを使用ContentControl.Contentしてデフォルトで描画されます。TextBlock.ToString()namespace.classnameViewModelContentControl

どこかで暗黙的を定義することによりDataTemplate(定義済み - noのみの a です)、オブジェクトの にバインドされたデフォルトを使用する代わりに、そのオブジェクトを描画しようとするたびに、指定された を使用して指定されたオブジェクトを描画するように WPF に指示します。ResourcesDataTemplateTargetTypex:KeyDataTemplateTextBlock.ToString()

DataTemplates暗黙的は以前のバージョンの Silverlight ではサポートされていませんが、5.0 以降ではサポートされていることに注意してください。以前のバージョンの Silverlight では、通常、代わりにDataTemplateSelectorを使用します。

于 2012-11-27T14:19:55.653 に答える
1

だから私は実際にこの問題を解決しました. MainView で datatemplates を作成する必要がない方法で、私は好きではありませんでした. ビューの切り替えについて話しているとき、MainViewは表示しているビューについて何も知らないはずです。

前提条件:このソリューションには、GalaSoft の MVVM Light を使用する必要があります。

これは私のテスト ソリューションです。2 つのボタンがMainViewに追加され、各ボタンが新しいビューを開きます。clickevent はコマンドにバインドされています。

<Button Content="TestView1" Grid.Column="1" Command="{Binding CallTestView1Command}" HorizontalAlignment="Left" Margin="185,17,0,0" VerticalAlignment="Top" Width="75"/>
<Button Content="TestView2" Grid.Column="1" Command="{Binding CallTestView2Command}" HorizontalAlignment="Left" Margin="280,17,0,0" VerticalAlignment="Top" Width="75"/>

MainViewには、切り替えることができるビューを含める必要がある Border があります。すべてのビューはUserControlから継承するため、コンテンツをMainViewModelのプロパティCurrentViewにバインドします。

    <Border x:Name="displayedView" Grid.Row="2">
        <UserControl Content="{Binding CurrentView}" />
    </Border>

MainViewModelには、CurrentView プロパティがあります。

 public const string CurrentViewPropertyName = "CurrentView";

    private UserControl _currentView;

    /// <summary>
    /// Sets and gets the "CurrentView property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public UserControl CurrentView
    {
        get
        {
            return _currentView;
        }

        set
        {
            if (_currentView == value)
            {
                return;
            }

            RaisePropertyChanging(CurrentViewPropertyName);
            _currentView = value;
            RaisePropertyChanged(CurrentViewPropertyName);
        }
    }

ボタンをクリックすると、対応する Command がMainViewModelで呼び出されます。

        private RelayCommand _callTestView1Command;
    public RelayCommand CallTestView1Command
    {
        get
        {
            return _callTestView1Command ??
                   (_callTestView1Command = new RelayCommand(() =>
                       {
                           CurrentView = new TestView1();
                       }));
        }
    }

    private RelayCommand _callTestView2Command;
    public RelayCommand CallTestView2Command
    {
        get
        {
            return _callTestView2Command ??
                   (_callTestView2Command = new RelayCommand(() =>
                   {
                       CurrentView = new TestView2();
                   }));
        }
    }

ご覧のとおり、 CurrentViewは PropertyTyChanged イベントを発生させるため、各コマンドはCurrentViewを新しいビューに設定し、MainView でビューが切り替わります

于 2012-10-16T07:14:51.047 に答える
1

最初に、ContentControl を介してビューを表示するのではなく、Silverlight ツールキットでナビゲーション フレームを使用することを検討することをお勧めします。また、ViewModel でビューを作成したくありません... それはあまり良くありません。ただし、ViewModel がビジネス ロジックを実行し、表示するビューを決定するかどうかは気にしません。ツールキットはこちらから入手できます: http://silverlight.codeplex.com/

メインページで XAML をセットアップします。

<Border x:Name="displayedView" Grid.Row="2"> 
        <navigation:Frame x:Name="ContentFrame" /> 
    </Border> 

MVVM Light を使用しているため、メッセージングを使用します。ビュー モデルは、ビューを変更するコマンドを取得し、変更するビューを決定してから、メイン ページにメッセージを送信してビューを変更するように指示します。

次のように、ナビゲート リクエストのメイン ページにリスナーをセットアップします。

public MainPage()
{
    InitializeComponent();  
    Messenger.Default.Register<Uri>(this, "NavigationRequest", (uri) => ContentFrame.Navigate(uri));
}

次に、ビュー モデルでコマンドをセットアップします。

    private RelayCommand _callTestView1Command;         
public RelayCommand CallTestView1Command         
{         
    get         
    {         
        return _callTestView1Command ??         
               (_callTestView1Command = new RelayCommand(() =>         
                   {         
                        Messenger.Default.Send<Uri>(new Uri("/Views/.../Page.xaml", UriKind.Relative), "NavigationRequest");

                   }));         
    }         
}   

これらは私のために働く基本です。これを拡張して、本当の「アーキテクチャ」を得ることができます。たとえば、ナビゲーション リクエストを送信するビュー モデルの基本クラスを作成したり、URI を生成するヘルパー クラスを作成したりできます (そのため、URI はアプリ内のあらゆる場所でハード コードされません)。頑張ってください!

于 2012-10-15T12:19:14.837 に答える
0

CurrentView は変更されますが、ビューのコンテンツを実際に表示する代わりに、インスタンス化された ViewModel の名前空間を表示するだけなので、これは実際にはある程度機能します。

CurrentViewプロパティをviewmodelインスタンスに変更し、それをコンテンツとしてバインドしているためです。コンテンツはビューである必要があり、そのビューの をビューモデルに設定する必要があるため、これは間違っていますDataContext

ここで実行できる最も簡単な方法は、コマンド内に View インスタンスを作成し、viewmodel をその DataContext として設定してから、ビューをCurrentViewプロパティに設定することです。もちろん、これはMVVM パターンに違反するため、この責任を別のコンポーネントに移す必要があります。独自のナビゲーション ロジックを作成する代わりに、既存のソリューションを利用することをお勧めします。この種のタスクは見た目ほど簡単ではありません。

Prismライブラリを使用することをお勧めします

于 2012-10-15T11:14:06.393 に答える