设置 AutoGenerateColumns=true 并按数据类型自动转换

Set AutoGenerateColumns=true and auto convert by the DataType

我有一个很大的 ObservableCollection,其中包含 40 多个不同类型的列。 一些列是列表。 我不想设置 AutoGenerateColumns=false 因为列的 amont 但数据网格在数据类型的字符串中显示它:System.Collection.Generic.List'1[System.double] 我想呈现一个字符串,如“10,2,30,5.2” 如果它是一个列表,我可以创建一个转换器来检查值的类型和 return 这样的字符串吗? 我如何从 Xaml 读取它(我使用 mvvm patteren) 谢谢!

WPF 的 DataGrid 列引发一个 AutoGeneratingColumn 事件,您可以使用该事件为一个或多个列自定义列的生成。它可以像更改列 header 一样简单,也可以像用您自己的自定义列模板替换 auto-generated 列一样复杂。有关示例,请参阅 this MSDN link

一个选项可能是将数据类型从 List 更改为您自己的 class 从 List 继承并覆盖 ToString 方法以 return 您想要的字符串。像这样:

public class MyDoubleList : List<double>
{
    public override string ToString()
    {
        string s = "";
        foreach (double d in this)
        {
            s = s + d.ToString() + ";";
        }
        return s;
    }
}

用法示例:

MyDoubleList l = new MyDoubleList();
l.Add(12);
l.Add(25);

string a = l.ToString();

有多种方法可以解决您的问题。您可以使用已更改的集合元素创建新的 ViewModel 以进行显示,或者在显示时更改 ViewModel 外部的数据。第二种方法使用在显示时更改自动生成列的概念。 MSDN

中的操作方法文章中描述了这种方法

好处是您可以使用这种方法对任何列执行任何操作,而无需创建单独的 类。

在下面的示例中,我正在更改 State Collection 的显示。

  1. 您需要处理 AutoGeneratingColumn 事件。

    <DataGrid x:Name="Dgrd" Canvas.Left="20" Canvas.Top="20" AutoGeneratingColumn="Dgrd_AutoGeneratingColumn"  />
    
  2. 用于显示集合元素的数据模板。

        <DataTemplate x:Key="CollectionTemplate">            
            <TextBlock Text="{Binding}" Loaded="TextBlock_Loaded" />            
        </DataTemplate>     
    
  3. 更改集合列的 AutoGeneratingColumn 事件处理程序:

        private void Dgrd_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {         
          if (e.PropertyType == typeof(ObservableCollection<State>))
          {
              e.Column = new DataGridTemplateColumn() { Header = "StateList", CellTemplate = (DataTemplate)FindResource("CollectionTemplate") };
          }
        }
    
  4. DataTemplate 的 TextBlock 的 Loaded 事件处理程序实际更改我们的收集数据以显示:

        private void TextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            var country = (Country)((TextBlock)e.OriginalSource).DataContext;
            var states = country.States.Select(c => c.Area + " : " + c.Capital + " : " + c.Name);
    
            string state_string = "";
            foreach (string s in states)
            {
                state_string = state_string + " ^ " + s;
            }
    
            ((TextBlock)e.OriginalSource).DataContext = state_string;
        }     
    
  5. 数据相关 类 :

    public class DataStore
    {
        public ObservableCollection<Country> Countries { get; set; }
    
        public DataStore()
        {
            Countries = new ObservableCollection<Country>();
            Countries.Add(new Country() { Area = 12345, Capital = "NewDelhi", Formed = DateTime.Parse("1/1/1990"), Name = "India",
                States = new ObservableCollection<State>() { new State() { Area = 112345, Capital = "Bhopal", Name = "MP" }, new State() { Area = 113456, Capital = "Lucknow", Name = "UP" } }
            });
            Countries.Add(new Country() { Area = 22345, Capital = "Washington DC", Formed = DateTime.Parse("1/1/1995"), Name = "USA",
                States = new ObservableCollection<State>() { new State() { Area = 212345, Capital = "Silicon Valley", Name = "Pennysylvania" }, new State() { Area = 213456, Capital = "NewYork", Name = "Old Trafford" } }
            });
        }
    }
    
    public class Country
    {
        public string Name { get; set; }
        public int Area { get; set; }
        public string Capital { get; set; }
        public DateTime Formed { get; set; }
        public ObservableCollection<State> States { get; set; }
    }
    
    public class State
    {
        public string Name { get; set; }
        public int Area { get; set; }
        public string Capital { get; set; }
    }
    
  6. Dgrd.ItemsSource = new DataStore();

显示: