0

radOutlookbar を使用して、さまざまなデータセット (ユーザー、国籍など) を画面に表示するアプリケーションがあります。問題なくデータを表示するために、各アイテムに必要なビューをロードすることができました。

次に、各データセット (ユーザー、国籍など) のビューを作成して、表示されたデータセット内で選択された各項目 (ユーザー) の詳細を表示しました。

ケース: まず、アイテムをクリックしたときに各データセットのそれぞれのビューを表示する必要があります。次に、表示されたビューには、表示された詳細を編集/追加するオプションがあります。

state-base-navigation を使用してこのシナリオを実現したいと考えています。

そのため、読み込まれたビューをホストするグリッドの ItemsPanelTemplate を持つ ItemsControl 内に PRISM 領域があり、基本的に各データセットのビューを読み込みます。

質問、VSM を使用して、選択したデータセットに従ってそれぞれのビューを表示/非表示にするにはどうすればよいですか?

質問 2: 各ビューの詳細を編集/追加するシナリオを有効にするために、読み込まれたビュー内に別のネストされた状態を定義できるようにする必要がありますか?

誰かがこれを行うアイデアを持っている場合は、開始コードを用意すると非常に役立ちます。よろしくお願いします

4

1 に答える 1

0

VSM にアクセスするための他のスキームがあるかもしれませんが、私はそのための AttachedProperty を作成することを好みます。説明させてください。

ここに VisualState マネージャーがあります

/// <summary>
/// Class will allow to change VisualSate on ViewModel via attached properties
/// </summary>
public static class VisualStateManagerEx
{
    private static PropertyChangedCallback callback = new PropertyChangedCallback(VisualStateChanged);

    /// <summary>
    /// Gets the state of the visual.
    /// </summary>
    /// <param name="obj">The obj.</param>
    /// <returns></returns>
    public static string GetVisualState(DependencyObject obj)
    {
        return (string)obj.GetValue(VisualStateProperty);
    }

    /// <summary>
    /// Sets the state of the visual.
    /// </summary>
    /// <param name="obj">The obj.</param>
    /// <param name="value">The value.</param>
    public static void SetVisualState(DependencyObject obj, string value)
    {
        obj.SetValue(VisualStateProperty, value);
    }

    /// <summary>
    /// DP for 'VisualState'
    /// </summary>
    public static readonly DependencyProperty VisualStateProperty =
        DependencyProperty.RegisterAttached(
            "VisualState",
            typeof(string),
            typeof(VisualStateManagerEx),
            new PropertyMetadata(null, VisualStateManagerEx.callback)
        );

    /// <summary>
    /// Visuals the state changed.
    /// </summary>
    /// <param name="d">The d.</param>
    /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
    public static void VisualStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //Control changeStateControl = d as Control;
        FrameworkElement changeStateControl = d as FrameworkElement;
        if (changeStateControl == null)
            throw (new Exception("VisualState works only on Controls type"));

        if (Application.Current.Dispatcher.CheckAccess() == false)
        {
            // Wrong thread
            System.Diagnostics.Debug.WriteLine("[VisualStateManagerEx] 'VisualStateChanged' event received on wrong thread -> re-route via Dispatcher");
            Application.Current.Dispatcher.BeginInvoke(
                //() => { VisualStateChanged(d, e); }
                VisualStateManagerEx.callback
                , new object[] { d, e });    //recursive
        }
        else
        {
            if (string.IsNullOrEmpty(e.NewValue.ToString()) == false)
            {
                //VisualStateManager.GoToState(changeStateControl, e.NewValue.ToString(), true);
                VisualStateManager.GoToElementState(changeStateControl, e.NewValue.ToString(), true);
                System.Diagnostics.Debug.WriteLine("[VisualStateManagerEx] Visual state changed to " + e.NewValue.ToString());
            }
        }
    }
}

今 - XAML では、次のように ViewModel にアタッチします。

<UserControl
     xmlns:VSManagerEx=clr-namespace:Namespace.namespace;assembly=Assembly01"
     VSManagerEx:VisualStateManagerEx.VisualState="{Binding Path=ViewModelVisualState, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
     ...
     ...

これで、XAML の VSM はViewModelVisualStateViewModelBase のプロパティにバインドされます (またはDataContextthisにバインドされるものは何でもUserControl。したがって、実際に使用している ViewModelBase は次のようになります。

/// <summary>
/// Base class for all 'view-models'
/// </summary>
[Export(typeof(ViewModelBase))]
public abstract class ViewModelBase : INavigationAware, INotifyPropertyChanged
{
    private SynchronizationContext parentSyncContent;

    #region VisualState
    private string viewModelVisualState = string.Empty;
    /// <summary>
    /// Gets or sets the state of the view model visual.
    /// </summary>
    /// <value>
    /// The state of the view model visual.
    /// </value>
    public virtual string ViewModelVisualState
    {
        get { return viewModelVisualState; }
        set
        {
            viewModelVisualState = value;
            RaisePropertyChanged(this, "ViewModelVisualState");
        }
    }
    #endregion

    /// <summary>
    /// Raises the property changed.
    /// </summary>
    /// <param name="Sender">The sender.</param>
    /// <param name="PropertyName">Name of the property.</param>
    public void RaisePropertyChanged(object Sender, string PropertyName)
    {
        parentSyncContent.Post((state) =>
        {
            if (PropertyChanged != null)
                PropertyChanged(Sender, new PropertyChangedEventArgs(PropertyName));
        }, null);
    }


    ...
    ...

したがって、この ViewModelBase から継承する任意の ViewModel で、独自の VMS 状態を宣言し、次のように管理できます。

    [Export(typeof(IViewModel1))
    public ViewModel1 : ViewModelBase, IViewModel1
    {

          private const string VM_STATE_WORKING = "WorkingState";

          internal void StartWorking()
          {
               this.ViewModelVisualState = VM_STATE_WORKING;
    ...
    ...

質問 2 について: いいえ - 何かの中で追加のビューを宣言する必要はありません。ナビゲーションに関する PRISM ドキュメントを参照してください。さまざまなプレゼンテーション ロジックをサポートする View/ViewModel の作成方法に関する優れた例があります。

これは役に立ちましたか?

于 2012-09-06T07:07:25.600 に答える