4

我有一个应用于 DataGridTemplateColumn 的 DataTemplateSelector。它正确地为我提供了一个 DataTemplate,它根据我的 DataRow(在其他列中)中的某些信息而有所不同。

到目前为止,一切都很好。

但是,当我现在更改网格中的数据时,这将导致选择器为该列选择不同的 DataTemplate,它不会自动显示这个新的 DataTemplate。

我在 Matthew MacDonald (Apress) 第 564 页的 C# 2008 中的 Pro WPF 中读到,这是已知问题,唯一的解决方法是释放选择器并重新应用它,当我的表中有很多记录时,这将非常慢。

有没有人找到解决这个问题的方法,或者在 .NET4 中有一个新功能可以解决这个问题?

谢谢

马塞尔

4

1 回答 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;
    }
}

编辑:我已经删除了我之前的答案,即使用转换器而不是选择器。这确实有效,但我认为这是一个更好的答案。

于 2012-06-28T06:02:03.543 回答