1

Windows 8 ストア アプリで、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 ViewModelの値に応じて View を UserControl に変更するにはどうすればよいですか?

私にとっての簡単な解決策はCurrentStatus、ViewModel からの と View からの別の文字列との間のバインディングを作成することでしたが、明らかにデータ バインディングはDependencyObject(文字列ではない) に対してのみ使用できます。

編集: xaml ファイルには、CurrentStatus に基づいてStackPanelを入れたいだけが含まれています。UserControlしたがって、UserControlOne などを含める必要があるCurrentStatus場合..."one"StackPanel

この問題に対するアイデアや良い解決策はありますか?

どうもありがとう!

4

3 に答える 3

2

私は通常 a を使用し、 aに基づいてContentControl設定しますContentTemplateDataTrigger

私のブログ投稿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に置き換えられました。私はまだこれを使用する機会がありませんでしたが、私が読んでいることによると、彼らは Silverlight と同じアプローチを WinRT に使用していました (これもDataTriggersv5 までサポートされていませんでした)。Silverlight に対する私の解決策は、DataTemplateSelector

それがあなたを正しい方向に向けることができることを願っています:)

于 2013-02-28T15:39:16.747 に答える
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をステータスにバインドしてコンバーターを使用するコンバーターを使用できます。

しかし、私が言ったように、より多くのコードが投稿されなければ、私はあなたが何を達成しようとしているのか100%明確ではありません

于 2013-02-28T15:33:34.597 に答える
1

DataTemplateSelector以前はそのような場合にandを使用していましたが、IValueConverter今では私のお気に入りのアプローチはVisualStateManager. ここで、WinRT XAML Toolkit で添付された動作パターンを実装する最も基本的な添付プロパティを作成しました。これは次のようになります。

/// <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
}

VisualStatesすべての表示状態を一覧表示する Silverlight Toolkitのクラスのような列挙型のクラスを定義する必要があります(重複を避けるため)。

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 を使用してその状態がどのように見えるかを定義できます。たとえば、レイアウト内のさまざまな要素の可視性を変更しContentたりContentTemplate、単に可視性を変更したりできます。ボタンをクリックするだけでビューを切り替えることができ、Blend でこれらのビューを更新できるため、この方法がデザイナー ツールを最もよくサポートしていると思います。

于 2013-02-28T18:35:07.170 に答える