2011-11-11 28 views
3

我已经在这几次在过去几个月中,但我无法弄清楚如何做到这一点。动态WPF数据网格与用户控件

我有一个DataGrid中要显示所有列一个可点击的用户控件除了第一个,这应该是没有编辑的可能性定期textcolumn。问题是列数必须是动态的,可以有2到n个。

因为我甚至不知道从哪里开始我没有任何的示例代码。

如果有人可以帮助我获得的轨道上,我将非常感激。该解决方案不必是适当的MVVM或非常花哨,它只需要工作。

+0

如何和何时你添加新列?它们是在创建DataGrid时定义的并且是静态的,还是根据用户交互动态添加的? – Rachel

+0

看一看这个问题:http://stackoverflow.com/questions/320089/how-do-i-bind-a-wpf-datagrid-to-a-variable-number-of-columns –

回答

0

UPDATE 1 - 包含自C#版本。

代码:

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.Collections.Specialized; 
using System.Globalization; 

namespace DynamicColumns 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      this.Loaded += 
       (o, e) => 
       { 
        this.PopulateItemsSource(); 
       }; 
     } 

     private void PopulateItemsSource() 
     { 
      int months = Math.Max(new Random().Next(12), 1); 

      this.d.ItemsSource = 
       new string[] 
       { 
        "John", 
        "Paul", 
        "Peter" 
       }.Select(t => 
        MonthlyPerformance.CreateDummy(t, months)).ToList(); 
     } 

     private void RePopulateButton_Click(object sender, RoutedEventArgs e) 
     { 
      this.PopulateItemsSource(); 
     } 
    } 

    #region "Interfaces - must be in the shared between Objects & UI" 

    public interface IDynamicPropertiesObject 
    { 
     Dictionary<string, string> Properties { get; } 
    } 

    #endregion 

    #region "Objects" 

    public class MonthlyPerformance : IDynamicPropertiesObject 
    { 
     public string PerformerName 
     { 
      get; 
      set; 
     } 

     public Dictionary<string, string> Properties 
     { 
      get; 
      private set; 
     } 

     public static MonthlyPerformance CreateDummy(string performerName, 
      int months) 
     { 
      if (months < 1 || months > 12) 
      { 
       throw new ArgumentException(months.ToString()); 
      } 

      Random random = new Random(); 

      return new MonthlyPerformance() 
      { 
       PerformerName = 
        performerName, 
       Properties = 
        Enumerable.Range(1, months).ToDictionary(k => new DateTime(1, k, 1).ToString("MMM"), v => random.Next(100).ToString()) 
      }; 
     } 
    } 

    #endregion 

    #region "UI" 

    internal class DynamicPropertyValueConverter: IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      IDynamicPropertiesObject o = value as IDynamicPropertiesObject; 

      if (o != null) 
      { 
       return o.Properties[parameter.ToString()]; 
      } 

      return Binding.DoNothing; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class ExtendedDataGrid: DataGrid 
    { 
     public static readonly DependencyProperty IsDynamicColumnProperty = 
      DependencyProperty.RegisterAttached("IsDynamicColumn", 
            typeof(Boolean), 
            typeof(ExtendedDataGrid), 
            new PropertyMetadata(false)); 

     private DynamicPropertyValueConverter converter = null; 

     public ExtendedDataGrid() 
     { 
      this.EnableColumnVirtualization = true; 
      this.EnableRowVirtualization = true; 
      this.AutoGenerateColumns = false; 
     } 

     private DynamicPropertyValueConverter Converter 
     { 
      get 
      { 
       if (this.converter == null) 
       { 
        converter = new DynamicPropertyValueConverter(); 
       } 

       return this.converter; 
      } 
     } 

     protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 
     { 
      base.OnItemsChanged(e); 

      this.ReGenerateColums(); 
     } 

     private bool TryGetDynamicColumn(out DataGridColumn column) 
     { 
      column = 
       this.Columns.FirstOrDefault(t=>(bool)t.GetValue(ExtendedDataGrid.IsDynamicColumnProperty)); 

      return column != null; 
     } 

     private void ClearDynamicColumns() 
     { 
      DataGridColumn column; 

      while (this.TryGetDynamicColumn(out column)) 
      { 
       this.Columns.Remove(column); 
      } 
     } 

     private void ReGenerateColums() 
     { 
      this.ClearDynamicColumns(); 

      if (this.Items.Count > 0) 
      { 
       IDynamicPropertiesObject o = 
        this.Items[0] as IDynamicPropertiesObject; 

       if (o != null) 
       { 
        foreach (KeyValuePair<string, string> property 
         in o.Properties) 
        { 
         DataGridTextColumn column = 
          new DataGridTextColumn() 
         { 
          Header = property.Key, 
          Binding = new Binding() 
          { 
           Converter = this.Converter, 
           ConverterParameter = property.Key 
          } 
         }; 

         column.SetValue(ExtendedDataGrid.IsDynamicColumnProperty, true); // so we can remove it, when calling ClearDynamicColumns 
         this.Columns.Add(column); 
        } 
       } 
      } 
     } 
    } 

    #endregion 
} 

标记:

<Window x:Class="DynamicColumns.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:DynamicColumns" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 
     <Button x:Name="RePopulateButton" Grid.Row="0" Click="RePopulateButton_Click">Re-Populate</Button> 
     <local:ExtendedDataGrid x:Name="d" Grid.Row="1"> 
      <local:ExtendedDataGrid.Columns> 
       <DataGridTextColumn Width="Auto" Binding="{Binding PerformerName}"/> 
      </local:ExtendedDataGrid.Columns> 
     </local:ExtendedDataGrid> 
    </Grid> 
</Window> 
+1

谢谢,但其中我能找到ColumnType吗? :)使用.NET 4.0。 – PerK

+0

如何上传项目 - 此处允许的服务是什么? – 2011-11-14 12:40:58

+0

我不确定有没有。如果你想要,你可以把它发送到[email protected]。谢谢! – PerK