2012-09-02 25 views
0

我有一个应用程序使用radOutlookbar在屏幕上显示不同的数据集(用户,国籍等)。 我已经设法加载每个项目中所需的视图来显示没有问题的数据。使用视觉状态管理器显示/隐藏视图silverlight&PRISM

然后,我为每个数据集(用户,国籍等)构建了视图,以在显示的数据集内显示每个选定项目(即:用户)的详细信息。

案例: 首先,当我点击它的项目时,我需要显示每个数据集的相应视图。 二,显示的视图将有一个选项来编辑/添加显示的细节。

我想使用基于状态的导航来实现这个场景。

因此, 我在ItemsControl中有一个PRISM区域,用网格的ItemsPanelTemplate来承载加载的视图,基本上我加载了每个数据集的视图。

问题, 如何根据所选数据集使用VSM显示/隐藏相应视图?

问题2: 我应该能够在加载的视图内定义另一个嵌套状态来启用编辑/添加每个视图的详细信息吗?

如果有人有任何想法做到这一点,将有很大的帮助,有一个起始代码。 此致敬礼

回答

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你把它连接到您的视图模型是这样的:

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

现在你在XAML VSM势必ViewModelVisualState财产ViewModelBase(或任何将被绑定到此UserControlDataContext。所以实际上你使用的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继承任何视图模型可以宣布它自己的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的例子。

对您有帮助吗?

+0

谢谢Jasper,我已经使用了“DataStateBehavior”,它的工作原理如下:当然,你需要混合才能工作。 – Waleed