2011-05-09 75 views
4

我有一個應用於DataGridTemplateColumn的DataTemplateSelector。 它正確地爲我提供了一個DataTemplate,它取決於DataRow(在其他列中)的某些信息。WPF DataTemplateSelector標準更改但模板不能重新應用?

到目前爲止這麼好。

但是,當我現在更改網格中的數據時,會導致該列的選擇器選擇不同的DataTemplate,因此它不會自動顯示此新的DataTemplate。

我在C#2008的Matthew MacDonald(Apress)第564頁的Pro WPF中讀到這是已知的問題,唯一的解決方法是釋放選擇器並重新應用這個,當我的記錄很多時會很慢表。

有沒有人找到解決這個問題的辦法,或者在.NET4中有一個新的功能可以解決這個問題?

感謝

馬塞爾

回答

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

編輯:我已刪除了我以前的答案這是使用一個轉換器,而不是一個選擇的。這確實奏效,但我認爲這是一個更好的答案。