2017-01-30 17 views
0

WPFでは、バインディングでスタイルとテンプレートを使用してコントロールを動的に変更できます。私はコントロールでUWPでこれを直接行う方法を見ていますが、バインディングに基づいて変更されるテンプレートを適用したいと思います。UWPでitemtemplateを動的に変更する方法は?

例はボタンです。私はこのプロジェクトでライトをオン/オフするボタンを持っています。プロジェクトは既にWPFで作成され実行されていますが、UWPに変換する必要があります。 WPFバージョンでは、ボタン用のLightStyleがあります。どのタイプのライトであるかによって、テンプレートを変更して、そのライト用に実行します。 (たとえば、いくつかのライトの色や暗さを変えることができます。また、いくつかのライトをオン/オフするだけですが、すべて同じLightStyleを使用します)。

どうすればいいですか? UWPで?私は一分捜され、私がここで止まり、私が掘り続けている間にチェックすると思った。このプロジェクトは純粋なMVVMであり、コードビハインドは使用されていないことに注意してください。私はそれが唯一の方法でない限り、説明の背後にあるコードを気にしません。事前に

感謝:)

+2

[DataTemplateSelector](https://msdn.microsoft.com/library/windows/apps/br209469)を使用して、ニーズに応じた適切なitemtemplateを関連付けることを考えましたか? – Romasz

+0

私はXAMLについてはかなり良いと思っていますが、実際にはDataTemplateSelectorは使用していませんので、少し戸惑っています。返信する前に私はそれについて学ぶために少し研究をしました。私はそれを完全に理解していません。私はViewModelの文字列を持っています。私はコントロールにテンプレート(例えばボタン)を適用し、文字列の値が適切なテンプレートを適用するかどうかに応じて適用したいと思います。これができるのであれば、簡単な例で少しでも気になるでしょうか?それがうまくいくなら、私は答えとしてマークして、それに関係なく投票します。 –

答えて

0

ここに私はそれが私の与えられた状況のために働く使用しています答えがあります。基本的には、VisualStateTriggerを使用し、コードを介して手動でトリガーを作成する必要があります。あなたが使用することができ、多くの組み込みがありますが、私がしなければならなかったこの状況のた​​めに、または少なくとも私は手動で1つ書く必要があったと思います。

ここにトリガーコードがあります。

public class StringComparisonTrigger : StateTriggerBase 
{ 
    private const string NotEqual = "NotEqual"; 
    private const string Equal = "Equal"; 

    public string DataValue 
    { 
     get { return (string)GetValue(DataValueProperty); } 
     set { SetValue(DataValueProperty, value); } 
    } 

    public static readonly DependencyProperty DataValueProperty = 
     DependencyProperty.Register(nameof(DataValue), typeof(string), typeof(StringComparisonTrigger), new PropertyMetadata(Equal, (s, e) => 
     { 
      var stringComparisonTrigger = s as StringComparisonTrigger; 
      TriggerStateCheck(stringComparisonTrigger, stringComparisonTrigger.TriggerValue, (string)e.NewValue); 
     })); 


    public string TriggerValue 
    { 
     get { return (string)GetValue(TriggerValueProperty); } 
     set { SetValue(TriggerValueProperty, value); } 
    } 

    public static readonly DependencyProperty TriggerValueProperty = 
     DependencyProperty.Register(nameof(TriggerValue), typeof(string), typeof(StringComparisonTrigger), new PropertyMetadata(NotEqual, (s, e) => 
     { 
      var stringComparisonTrigger = s as StringComparisonTrigger; 
      TriggerStateCheck(stringComparisonTrigger, stringComparisonTrigger.DataValue, (string)e.NewValue); 
     })); 


    private static void TriggerStateCheck(StringComparisonTrigger elementTypeTrigger, string dataValue, string triggerValue) 
     => elementTypeTrigger.SetActive(dataValue == triggerValue); 
} 

これ、私は以下掲載しますようStateTriggerBaseから継承するVisualStateTriggersグループで使用することができるからです。私が知りませんでしたのは、あなたが書いた依存関係のプロパティはXAMLで使用でき、それを動作させるためのインターフェイスや何もトリガがないということです。トリガを起動するコードの唯一の行は、状態を変更したいときは常に呼び出さなければならない 'SetActive(ブール値)'です。 XAMLで依存関係のプロパティとバインドを行うと、プロパティが変更されるたびにSetActiveが起動され、ビジュアル状態が変更されます。

DataTemplateは以下のとおりです。

<DataTemplate x:Key="LightsButtonTemplate"> 

    <UserControl> 
     <StackPanel Name="panel"> 

      <VisualStateManager.VisualStateGroups> 
       <VisualStateGroup> 
        <VisualState> 
         <VisualState.StateTriggers> 
          <DataTriggers:StringComparisonTrigger DataValue="{Binding Type}" 
                    TriggerValue="READ" /> 
         </VisualState.StateTriggers> 
         <VisualState.Setters> 
          <Setter Target="panel.(UIElement.Background)" 
            Value="Red" /> 
         </VisualState.Setters> 
        </VisualState> 
       </VisualStateGroup> 
      </VisualStateManager.VisualStateGroups> 

      <TextBlock Text="{Binding Type}" /> 
      <TextBlock Text="{Binding LightStateViewModel.On}" /> 

     </StackPanel> 
    </UserControl> 

</DataTemplate> 

そして最後に、あなたはどこでものDataTemplateを使用することができます使用するが、私はLightViewModelsのリストにバインドされているItemsControlにでそれを使用しています。

<ScrollViewer Grid.Row="1"> 
     <ItemsControl ItemsSource="{Binding LightViewModels}" 
         ItemTemplate="{StaticResource LightsButtonTemplate}" /> 
    </ScrollViewer> 

明らかにこれは私がライトボタン用にしたいテンプレートデザインではありませんが、これは私が理解して今ダイナミックテンプレートを実装するためのすべてです。うまくいけば、これは他の誰かがWPFから来るのを助けるでしょう。

StateTriggerBaseから派生したカスタムトリガクラスは、必要に応じてバインドしてバインドできます。そのトリガを更新するときはいつでもSetActive(true)またはSetActive(false)を呼び出すだけです。それが真であれば、そのトリガーを使用するVisualStateはアクティブになります。

1

Here is a sample I've made - XAML:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Orientation="Horizontal"> 
    <StackPanel.Resources> 
     <local:MySelector x:Key="MySelector"> 
      <local:MySelector.GreenTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Text}" Foreground="Green"/> 
       </DataTemplate> 
      </local:MySelector.GreenTemplate> 
      <local:MySelector.RedTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Text}" Foreground="Red"/> 
       </DataTemplate> 
      </local:MySelector.RedTemplate> 
     </local:MySelector> 
    </StackPanel.Resources> 

    <ListView x:Name="ListOfItems" Width="100" ItemTemplateSelector="{StaticResource MySelector}"/> 
    <StackPanel> 
     <ToggleSwitch OnContent="GREEN" OffContent="RED" Margin="10" IsOn="{x:Bind IsSwitched, Mode=TwoWay}"/> 
     <Button Content="Add item" Click="AddClick" Margin="10"/> 
    </StackPanel> 
</StackPanel> 

と背後にあるコード:一般的に、あなたの選択のための各種のスイッチを選択することができます

public sealed partial class MainPage : Page, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 

    private bool isSwitched = false; 
    public bool IsSwitched 
    { 
     get { return isSwitched; } 
     set { isSwitched = value; RaiseProperty(nameof(IsSwitched)); } 
    } 

    public MainPage() { this.InitializeComponent(); } 

    private void AddClick(object sender, RoutedEventArgs e) 
    { 
     ListOfItems.Items.Add(new ItemClass { Type = isSwitched ? ItemType.Greed : ItemType.Red, Text = "NEW ITEM" }); 
    } 
} 

public enum ItemType { Red, Greed }; 

public class ItemClass 
{ 
    public ItemType Type { get; set; } 
    public string Text { get; set; } 
} 

public class MySelector : DataTemplateSelector 
{ 
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     switch ((item as ItemClass).Type) 
     { 
      case ItemType.Greed: 
       return GreenTemplate; 
      case ItemType.Red: 
      default: 
       return RedTemplate; 
     } 
    } 

    public DataTemplate GreenTemplate { get; set; } 
    public DataTemplate RedTemplate { get; set; } 
} 

、それはあなたのニーズによって異なります。上記の例では、アイテムのプロパティに基づいてテンプレートhere is a good exampleのアイテムのタイプを切り替える方法を切り替えています。

関連する問題