繁体   English   中英

如何强制重新选择DataTemplateSelector

[英]How to force re-selection of DataTemplateSelector

我在UWP上的ListBox上使用DataTemplateSelector,我想为现有ListBoxItem强制重新选择DataTemplate。 使它起作用的唯一方法是从绑定集合中删除该项目,然后重新添加该项目。 这确实看起来像克鲁格。 我只是想使列表框项目的布局无效,并使其再次调用数据模板选择器。 似乎无法做到这一点。

这是页面...

<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()不强制重新选择模板?

非常感谢@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;
    }

暂无
暂无

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

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