2017-08-09 18 views
0

ListBoxのUWPでDataTemplateSelectorを使用していて、既存のListBoxItemのDataTemplateを強制的に再選択したいとします。私はそれを動作させることができる唯一の方法は、バインドされたコレクションからアイテムを削除し、アイテムを再追加することです。これは本当にクルージュのようです。私は単に、リストボックス項目のレイアウトを無効にして、データテンプレートセレクタを再度呼び出すようにしたいと思います。これをするように見えることはできません。ここでDataTemplateSelectorの再選択を強制的に行う方法

がページです...ここで

<Page.Resources> 
    <local:MyTemplateSelector x:Key="TemplateSelector"/> 
</Page.Resources> 
<Page.DataContext> 
    <local:MyViewModel/> 
</Page.DataContext> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <StackPanel> 
     <ListBox x:Name="listBox1" Margin="5" ItemsSource="{Binding QuantityRows}" 
      ItemTemplateSelector="{StaticResource TemplateSelector}"> 
      <ListBox.Resources> 
       <DataTemplate x:Key="Detail"> 
        <StackPanel Orientation="Horizontal"> 
         <Button Click="OnShowSummary">Show Summary</Button> 
         <TextBlock Text="Name "/> 
         <TextBox Width="40" Text="{Binding Name}"/> 
        </StackPanel> 
       </DataTemplate> 
       <DataTemplate x:Key="Summary"> 
        <StackPanel Orientation="Horizontal"> 
         <Button Click="OnShowDetail">Show Detail</Button> 
         <TextBlock Text="{Binding Summary}"/> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.Resources> 
     </ListBox> 
    </StackPanel> 

</Grid> 

は、テンプレートセレクタである...ここで

public class MyTemplateSelector : DataTemplateSelector 
{ 
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     QuantityRow row = item as QuantityRow; 
     ListBox lb = UWPUtilities.GetParent<ListBox>(container); 
     if (row != null && lb != null) 
     { 
      if (row.IsDetail) 
      { 
       return lb.Resources["Detail"] as DataTemplate; 
      } 
      else 
      { 
       return lb.Resources["Summary"] as DataTemplate; 
      } 
     } 
     return base.SelectTemplateCore(item, container); 
    } 
} 

は、ビューモデルである...

public class QuantityRow 
{ 
    public bool IsDetail { get; set; } 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Summary 
    { 
     get 
     { 
      return "Name = " + Name; 
     } 
    } 
} 
public class MyViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    public ObservableCollection<QuantityRow> QuantityRows { get; set; } 
    public MyViewModel() 
    { 
     QuantityRows = new ObservableCollection<QuantityRow>(); 
     QuantityRows.Add(new QuantityRow() { IsDetail = false, ID = 1, Name = "Length" }); 
     QuantityRows.Add(new QuantityRow() { IsDetail = true, ID = 2, Name = "Diameter" }); 
     QuantityRows.Add(new QuantityRow() { IsDetail = false, ID = 3, Name = "Temperature" }); 
     QuantityRows.Add(new QuantityRow() { IsDetail = false, ID = 4, Name = "Pressure" }); 
     QuantityRows.Add(new QuantityRow() { IsDetail = true, ID = 5, Name = "Angle" }); 
    } 
} 

ここにありますコードの後ろに...

public MyViewModel ViewModel 
    { 
     get 
     { 
      return DataContext as MyViewModel; 
     } 
    } 

    private void OnShowSummary(object sender, RoutedEventArgs e) 
    { 
     QuantityRow row = (sender as Button).DataContext as QuantityRow; 
     row.IsDetail = false; 
    //   UpdateLayout1(row); 
     UpdateLayout2(sender); 
    } 
    private void OnShowDetail(object sender, RoutedEventArgs e) 
    { 
     QuantityRow row = (sender as Button).DataContext as QuantityRow; 
     row.IsDetail = true; 
    //   UpdateLayout1(row); 
     UpdateLayout2(sender); 
    } 
    private void UpdateLayout1(QuantityRow row) 
    { 
     int index = ViewModel.QuantityRows.IndexOf(row); 
     ViewModel.QuantityRows.RemoveAt(index); 
     ViewModel.QuantityRows.Insert(index, row); 
    } 
    private void UpdateLayout2(object sender) 
    { 
     ListBoxItem lbi = UWPUtilities.GetParent<ListBoxItem>(sender as DependencyObject); 
     lbi.InvalidateArrange(); 
    } 

は、最後にここに要約し、詳細テンプレートを切り替えます各リスト項目のボタンがあります...

public static class UWPUtilities 
{ 
    public static T GetParent<T>(DependencyObject d) where T : class 
    { 
     while (d != null && !(d is T)) 
     { 
      d = VisualTreeHelper.GetParent(d); 
     } 
     return d as T; 
    } 
} 

ユーティリティ関数です。 UpdateLayout1はうまく動作しますが、バインドされたリストのチャーンビットを犠牲にしてください。 UpdateLayout2は機能しません。これは私の見解ではよりクリーンな実装となるでしょう。なぜListBoxItemのInvalidateArrange()がテンプレートの再選択を強制しないのですか?

+1

はあなたにいくつかのアイデアを与えるべきである[ここ](https://stackoverflow.com/questions/44249232/uwp-datatemplateselector-and-selecteditem/44251390#44251390)私の答えを見てください。モデルでINPCを実装する必要があるので、セレクタクラス内でPropertyChangedイベントを利用することができます。 –

+0

それは間違いなく動作しますが、うわーは醜いです。したがって、テンプレートセレクタをnullに設定してから、それを元に戻します。 Pffffffffffft。 – AQuirky

答えて

0

このアイディアのおかげで@Justin XLに非常に感謝しています。テンプレートセレクタを再度起動させるには、それをnullに設定してから同じ参照に戻す必要があります。これは確かに別のklugeですが、私は最初のklugeよりも少し良いです。ここで見つけられる優雅さはありません。

private void UpdateLayout2(object sender) 
    { 
     ListBoxItem lbi = UWPUtilities.GetParent<ListBoxItem>(sender as DependencyObject); 
     DataTemplateSelector dts = lbi.ContentTemplateSelector; 
     lbi.ContentTemplateSelector = null; 
     lbi.ContentTemplateSelector = dts; 
    } 
関連する問題