WPF DataTemplateSelector 的条件更改,但模板未被重新应用?

4
我有一个 DataTemplateSelector,它应用于 DataGridTemplateColumn。它可以根据我的 DataRow 中的某些信息(在其他列中)正确地提供不同的 DataTemplate。
到目前为止一切都很好。
然而,当我在网格中更改数据时,如果该列的选择器选择了不同的 DataTemplate,则不会自动显示此新 DataTemplate。
我在Matthew MacDonald(Apress)的Pro WPF in C# 2008第564页上读到了这个已知问题,解决办法是释放选择器并重新应用它,但在我的表中有许多记录时,这样做会非常慢。
有人找到了解决方法吗?或者在.NET4中是否有新功能可以解决这个问题?
谢谢。
Marcel
1个回答

3

一种解决方案是在单元格内放置一个ContentPresenter。这样,当内容发生更改时,ContentPresenter将再次从选择器中请求模板。例如:

<Window
    x:Class="TestSAS.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:TestSAS">

    <Window.Resources>        
        <local:MySelector x:Key="mySelector">
            <local:MySelector.UpperTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="upper - "></TextBlock>
                        <TextBlock Text="{Binding}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </local:MySelector.UpperTemplate>
            <local:MySelector.LowerTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="lower - "></TextBlock>
                        <TextBlock Text="{Binding}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </local:MySelector.LowerTemplate>
        </local:MySelector>
    </Window.Resources>

    <DockPanel>
        <Button DockPanel.Dock="Bottom" Click="doit_Click">Do It</Button>
        <DataGrid Name="mainGrid" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ContentPresenter Content="{Binding FirstName}" ContentTemplateSelector="{StaticResource mySelector}"></ContentPresenter>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>
</Window>

代码及其后台:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace TestSAS
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            mainGrid.ItemsSource = "Bob,mary,frank,George".Split(',').Select(s => new Person() { FirstName = s }).ToArray();
        }

        private void doit_Click(object sender, RoutedEventArgs e)
        {
            ((Person[])mainGrid.ItemsSource)[2].FirstName = "Frank";
        }
    }

    public class MySelector : DataTemplateSelector
    {
        public DataTemplate UpperTemplate { get; set; }
        public DataTemplate LowerTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var st = item as string;
            if (st == null) return null;
            if (st.Substring(0, 1).ToString().ToLower() == st.Substring(0, 1).ToString()) return LowerTemplate;
            return UpperTemplate;
        }
    }

    public class Person : INotifyPropertyChanged
    {
        private string firstName;

        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

编辑:我已经删除了之前的解答,该解答建议使用转换器而不是选择器。虽然那个方法也可以工作,但我认为这个答案更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接