2011-11-11 29 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