2013-02-28 105 views
1

如何在Windows 8商店應用程序中基於ViewModel的屬性在View中的UserControl之間進行更改?根據ViewModel的屬性在View中的UserControls之間切換

說我的ViewModel有它看起來像這樣的屬性:

class MyViewModel 
    { 
     public string CurrentStatus 
     { 
      get { return (string)GetValue(CurrentStatusProperty); } 
      set { SetValue(CurrentStatusProperty, value); } 
     } 

     public static readonly DependencyProperty CurrentStatusProperty = 
      DependencyProperty.Register("CurrentStatus", typeof(string), typeof(MyViewModel), new PropertyMetadata("default", CurrentStatusChanged)); 


     ... 
    } 

如何讓我的視圖根據CurrentStatus從視圖模型的值更改的用戶控件?

對我來說,strightforward的解決辦法是創建CurrentStatus從視圖模型和視圖另一個字符串之間的綁定,但顯然數據綁定只能用於DependencyObject(其中一個字符串不)。

編輯: XAML文件只包含一個StackPanel中,我想提出一個UserControl的基礎上,CurrentStatus。所以,如果CurrentStatus"one"我想StackPanel包含UserControlOne等等......

任何想法或很好的解決方案,以解決這個問題?

非常感謝!

回答

1

不知道我完全理解你在做什麼。你可以發佈xaml嗎?

如果你正在想是基於狀態以不同的方式呈現控件,然後使用一個轉換器,你可以提出基於狀態的不同的模板:

public class StatusToTemplateConverter : IValueConverter 
{ 
    #region IValueConverter Members 


    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     switch ((string) value) 
     { 
      case "Status1": 
       return Application.Current.Resources["Status1Template"]; 
      case "Status2": 
       return Application.Current.Resources["Status2Template"]; 

      default: 
       return Application.Current.Resources["Status3Template"]; 
     } 
    } 


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return null; 
    } 

    #endregion 
} 

上述假設你有你的模板定義在一個資源文件中

如果你想要做的只是一些簡單的事情,比如Status1的紅色文本或者status2的綠色文本,你可以有一個轉換器將狀態轉換爲顏色並將FontColor綁定到狀態並使用轉換器。

但就像我說的,沒有更多的代碼被張貼,我不是你想什麼來實現

1

我通常使用一個ContentControl,並設置根據DataTrigger

ContentTemplate 100%清晰我有張貼Switching between Views/UserControls using MVVM在我的博客的例子,但這裏有什麼可以像使用您的方案的示例:

<DataTemplate x:Key="DefaultTemplate"> 
    <local:DefaultUserControl /> 
</DataTemplate> 

<DataTemplate x:Key="ClosedTemplate"> 
    <local:ClosedUserControl /> 
</DataTemplate> 

<Style x:Key="MyContentControlStyle" TargetType="{x:Type ContentControl}"> 
    <Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" /> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding CurrentStatus}" Value="Closed"> 
      <Setter Property="ContentTemplate" Value="{StaticResource ClosedTemplate}" /> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 

... 

<ContentControl Style="{StaticResource MyContentControlStyle}" /> 

編輯

顯然DataTriggers在WinRT中不受支持,並已被替換爲VisualStateManager。我還沒有機會使用它,但是從我閱讀的內容來看,他們對WinRT使用與Silverlight相同的方法(在第5版中也不支持DataTriggers),而我的Silverlight解決方案是使用一個DataTemplateSelector

我希望可以爲您指出正確的方向:)

+0

對不起,您的代碼在Windows 8應用程序項目中不起作用。 Visual Studio抱怨說「Windows應用程序項目中不支持」類型「。對於'x:Type',如果我解決了''有問題。 – 2013-02-28 17:01:32

+0

@alex_and_ra我每天都會學到新的東西:)根據[這個答案](http://stackoverflow.com/a/7446841/302677),DataTriggers被[VisualStateManager](http://msdn.microsoft.com)取代。我在WinRT – Rachel 2013-02-28 17:05:26

+0

我從來沒有使用過DataTriggers或VisualStateManager ..我有點新的:)我要去試一試。謝謝! – 2013-02-28 17:19:48

1

雖然我以前使用過的DataTemplateSelectorIValueConverter在這種情況下 - 現在我最喜歡的方法是使用VisualStateManager。我創建了一個實現中的WinRT XAML工具包here的附加行爲模式的最基本的附加屬性 - 看起來像這樣:

/// <summary> 
/// Defines an attached property that controls the visual state of the element based on the value. 
/// </summary> 
public static class VisualStateExtensions 
{ 
    #region State 
    /// <summary> 
    /// State Attached Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty StateProperty = 
     DependencyProperty.RegisterAttached(
      "State", 
      typeof(string), 
      typeof(VisualStateExtensions), 
      new PropertyMetadata(null, OnStateChanged)); 

    /// <summary> 
    /// Gets the State property. This dependency property 
    /// indicates the VisualState that the associated control should be set to. 
    /// </summary> 
    public static string GetState(DependencyObject d) 
    { 
     return (string)d.GetValue(StateProperty); 
    } 

    /// <summary> 
    /// Sets the State property. This dependency property 
    /// indicates the VisualState that the associated control should be set to. 
    /// </summary> 
    public static void SetState(DependencyObject d, string value) 
    { 
     d.SetValue(StateProperty, value); 
    } 

    /// <summary> 
    /// Handles changes to the State property. 
    /// </summary> 
    /// <param name="d"> 
    /// The <see cref="DependencyObject"/> on which 
    /// the property has changed value. 
    /// </param> 
    /// <param name="e"> 
    /// Event data that is issued by any event that 
    /// tracks changes to the effective value of this property. 
    /// </param> 
    private static void OnStateChanged(
     DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var stateName = (string)e.NewValue; 
     var ctrl = (Control)d; 
     VisualStateManager.GoToState(ctrl, stateName, true); 
    } 
    #endregion 
} 

你應該這樣定義在Silverlight工具包的VisualStates類,列出所有的枚舉樣式類你的視覺狀態(所以你沒有重複),例如

internal static class VisualStates 
{ 
    #region GroupCommon 
    /// <summary> 
    /// Common state group. 
    /// </summary> 
    public const string GroupCommon = "CommonStates"; 

    /// <summary> 
    /// Normal state of the Common state group. 
    /// </summary> 
    public const string StateNormal = "Normal"; 

    /// <summary> 
    /// Normal state of the Common state group. 
    /// </summary> 
    public const string StateReadOnly = "ReadOnly"; 

    /// <summary> 
    /// MouseOver state of the Common state group. 
    /// </summary> 
    public const string StateMouseOver = "MouseOver"; 

    /// <summary> 
    /// Pressed state of the Common state group. 
    /// </summary> 
    public const string StatePressed = "Pressed"; 

    /// <summary> 
    /// Disabled state of the Common state group. 
    /// </summary> 
    public const string StateDisabled = "Disabled"; 
    #endregion GroupCommon 

    #region GroupFocus 
    /// <summary> 
    /// Focus state group. 
    /// </summary> 
    public const string GroupFocus = "FocusStates"; 

    /// <summary> 
    /// Unfocused state of the Focus state group. 
    /// </summary> 
    public const string StateUnfocused = "Unfocused"; 

    /// <summary> 
    /// Focused state of the Focus state group. 
    /// </summary> 
    public const string StateFocused = "Focused"; 
    #endregion GroupFocus 
} 

一旦你有這些 - 你可以在你的視圖模型的屬性一樣

public string VisualState { get; set; /* Raise PropertyChange event your preferred way here */ } 

而且在你看來說

<Page 
    ... 
    xmlns:extensions="using:WinRTXamlToolkit.Controls.Extensions" 
    extensions:VisualStateExtensions.State="{Binding VisualState}">... 

然後您的視圖模型可以輕鬆驅動的變化的視覺狀態,你可以使用Blend來定義該狀態的外觀 - 例如更改ContentContentTemplate或僅更改佈局中各個元素的可見性。我認爲這種方法對設計工具有最好的支持,因爲您可以通過點擊按鈕在視圖之間切換並在Blend中更新這些視圖。

+0

對於這一行'擴展:VisualStateExtensions.State =「{綁定狀態}」>它說「在類型'VisualStateExtensions'」中找不到可附加屬性'狀態'。另外,誰應該從綁定中'國家'? – 2013-02-28 19:59:55

+0

我答案中的'VisualStateExtensions'類具有State屬性。只要確保你在你的XAML的根XML元素中使用:WinRTXamlToolkit.Controls.Extensions「'添加'xmlns:extensions =」。對不起,我錯過了綁定中的State屬性實際上應該稱爲'VisualState',它來自我在第三個代碼塊中引用的視圖模型屬性。讓我更新它。 – 2013-02-28 21:03:09

相關問題