0

こんにちは友人、私はMVVM WPF アプリケーションを開発しています。TelerikRadTabコントロールのSelectionChangedイベントのイベントを実行する必要があります。MVVMライトを使用すると、EventToCommand 動作を使用するのは簡単ですが、MVVM フレームワーク (リンク) を使用しているため、使用する必要があります。インタラクション トリガーは @Link を提案しました。

以下では、インタラクティブな dll 参照を追加しました。

C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\Silverlight\v4.0

そしてXAMLに私が含めた

xmlns:I="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity



<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
     <Command:ChangePropertyOnTarget
          Target="{Binding}" PropertyName="SelectedItems"
          Value="{Binding SelectedItems, ElementName=ItemsToChoose}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>

アプリをビルドすると、以下のエラーが発生します。

プロパティ 'EventName' は、XML 名前空間 ' Link 'に存在しません。

これに関する提案やヘルプは非常に役立ちます。

4

1 に答える 1

0

私は mvvm light を使用していますが、イベント コマンド機能を頻繁に使用する必要はありません。少し異なる方法で、同じ機能を管理しました。

<telerik:RadTabControl Template="{StaticResource TabControlTemplate}" 
                ItemsSource="{Binding TabbedViewModels }" SelectedItem="{Binding ActiveTabbedViewModel, Mode=TwoWay}"
                ItemTemplate="{StaticResource TabItemTemplate}" Style="{StaticResource RadTabControlStyleBorderless}" />

そのため、メイン ウィンドウのビューモデルには、コントロールの項目ソースとしてバインドするタブ付き項目ごとに 1 つのビューモデルのコレクションがあります。次に、選択した項目をメイン ビュー モデルのプロパティにバインドします。次に、そのプロパティのセッターで、SelectionChangedEvent で行う必要がある特定のことを行うことができます。私の場合、タブのビューモデルはユーザーが開始したものに基づいて動的にロードされ、それぞれがかなり異なる可能性があるため、インターフェイスを使用することもできますが、すべて共通の基本クラスから継承します。したがって、コレクションはそのbasクラスのObservableCollectionであり、selectedItemがバインドするActiveTabbedViewModelプロパティもそのタイプです。

あなたのシナリオに適しているかどうかはわかりませんが、このアプローチを使用することで、相互作用トリガーは必要ありません

編集: もう少し詳しく説明します - 残念ながら、私はあなたを指すブログを知らないので、私がこれにどのようにアプローチしたかについてもう少し説明します

したがって、TabControl とコンテンツ フレームを含む MainPage.xaml です。MainPageViewModel は、メインページのビュー モデルです。TabbedWindowViewModelBase (この目的のために作成したクラス) の ObservableCollection である TabbedViewModels というプロパティがあります。

        /// <summary>
    /// Gets or sets a collection of TabbedViewModels - each one will be represented by a tab on the top bar of the main window
    /// </summary>
    public ObservableItemCollection<CastleTabbedWindowViewModelBase> TabbedViewModels
    {
        get
        {
            return this.tabbedViewModels;
        }

        set
        {
            this.tabbedViewModels = value;
            this.RaisePropertyChanged(() => this.TabbedViewModels);
        }
    }

        /// <summary>
    /// Gets or sets the Active Tab - is bound to the Tab bars SelectedItem - when changing to
    /// another tab / view model it sets the page menu item to the correct one for that view model
    /// </summary>
    public CastleTabbedWindowViewModelBase ActiveTabbedViewModel
    {
        get
        {
            return this.activeTabbedViewModel;
        }

        set
        {
            this.activeTabbedViewModel = value;
            this.RaisePropertyChanged(() => this.ActiveTabbedViewModel);

            if (value != null)
            {
                // when the active tab has changed want to ensure we open the previously opened page that the new tab was on
                value.DoSomething();
            }
        }
    }

この時点では、シナリオがどれほど複雑かによって異なります。同じビューを持っていて、データを変更しているだけの場合、ビューは ActiveTabbedViewModel にバインドできます。これは、propertychanged イベントが発生するためです。これにより、バインドが自動的に更新され、新しいタブに関連するデータが表示されます。子ビューモデルで DoSomething を使用して、そのデータを最初にロードすることができます。リフレッシュする必要がない限り、これを行う必要があるのは 1 回だけです。

あなたが説明したことから、これを回避する1つの方法は、以下の TabbedWindowViewModel クラスを作成することです:`

public class TabbedWindowViewModel :ViewModelBase
{
    private RelayCommand<NavigationEventArgs> navigationCommand;

    /// <summary>
    /// Gets or sets the position /order that this tab item is relative to the other tab items
    /// </summary>
    public int MenuOrder { get; set; }

    /// <summary>
    /// Gets or sets the Navigation Id
    /// </summary>
    public int NavigationId { get; set; }

    /// <summary>
    /// Gets or sets the Title that will be displayed for this tab item
    /// </summary>
    public string Title { get; set; }

    /// <summary>
    /// Gets or sets the navigation target that will be navigated to when the tab item is clicked
    /// </summary>
    public string NavigationTarget { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether the tab item is enabled
    /// </summary>
    public bool IsEnabled { get; set; }

    /// <summary>
    /// Gets the command for regular navigation.
    /// </summary>
    public virtual ICommand NavigationCommand
    {
        get
        {
            return this.navigationCommand
                   ??
                   (this.navigationCommand =
                    new RelayCommand<NavigationEventArgs>(
                        this.ExecuteNavigationCommand, x => this.IsEnabled));
        }
    }

   public void DoSomething()
   {
       //do whatever you need to
       //then navigate to the correct page
       this.NavigationCommand.Execute(null);

   }

    private void ExecuteNavigationCommand(NavigationEventArgs e)
    {
        NavigationManager.NavigateToView(this.NavigationTarget);
    }


}

NavigationManager は、ナビゲーションを支援する静的ヘルパー クラスであることに注意してください。次に、ナビゲートする可能性のある各ビューは、MainPage からデータコンテキストを継承するため、2 つの選択肢があります。TabbedWindoViewModel に DataViewModel プロパティを設定し、ActiveTabbedWindow.DataViewModel を介してすべてをそれにバインドします。または、メイン ビュー モデルの子ビュー モデルごとにプロパティを用意し、そのプロパティに直接バインドします。

        public SummaryViewModel SummaryViewModel
    {
        get
        {
                  return this.summaryViewModel
                  ?? (this.summaryViewModel = (SummaryViewModel)ViewModelFactory.GetPageViewModel<SummaryViewModel>());
        }
    }

お役に立てれば...

于 2012-10-30T13:00:37.803 に答える