简体   繁体   English

如何强制重新选择DataTemplateSelector

[英]How to force re-selection of DataTemplateSelector

I am using a DataTemplateSelector in UWP on a ListBox and I want to force a re-selection of the DataTemplate for an existing ListBoxItem. 我在UWP上的ListBox上使用DataTemplateSelector,我想为现有ListBoxItem强制重新选择DataTemplate。 The only way I can get it to work is to remove the item from the bound collection and then re-add the item. 使它起作用的唯一方法是从绑定集合中删除该项目,然后重新添加该项目。 This really seems like a kluge. 这确实看起来像克鲁格。 I would simply like to invalidate the layout of the list box item and get it to call the data template selector again. 我只是想使列表框项目的布局无效,并使其再次调用数据模板选择器。 Cannot seem to do this. 似乎无法做到这一点。

Here is the page... 这是页面...

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

Here is the template selector... 这是模板选择器...

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);
    }
}

Here is the view model... 这是视图模型...

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" });
    }
}

Here is the code behind... 这是背后的代码...

    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();
    }

Finally here is a utility function... 最后是一个实用程序功能...

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

There is a button on each list item that toggles between the summary and detail templates. 每个列表项上都有一个按钮,可在摘要模板和详细信息模板之间切换。 The UpdateLayout1 works fine, at the cost of a bit of churn in the bound list. UpdateLayout1可以正常工作,但会在绑定列表中造成一些混乱。 UpdateLayout2 does not work. UpdateLayout2不起作用。 This is the one would be a cleaner implementation in my view. 我认为这将是一种更清洁的实现。 Why doesn't InvalidateArrange() on the ListBoxItem force a reselection of the template? 为什么ListBoxItem上的InvalidateArrange()不强制重新选择模板?

Thanks very much to @Justin XL for this idea. 非常感谢@Justin XL的这个想法。 In order to get the template selector to fire again you have to set it to null and then set it back to the the same reference. 为了使模板选择器再次启动,您必须将其设置为null,然后将其设置回相同的引用。 This is indeed another kluge but I like it slightly better than my first kluge. 这确实是另一种克鲁格,但我喜欢它比我的第一个克鲁格略好。 No elegance to be found here. 在这里找不到优雅。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM