2017-08-09 28 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,然後將其設置回相同的引用。這確實是另一種方式,但我喜歡它比我的第一個更好。沒有優雅在這裏找到。

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