2010-06-17 16 views
18

DataGrid의 열을 MvvM 방식의 ToolKit 동적에서 만드는 방법을 찾고 있습니다. 그러나 불가능한 것처럼 보입니다!WPF MvvM DataGrid 동적 열

뭔가해야 할 것이 있습니까?

UserControl 또는 DataGrid에서 오는 다른 컨트롤을 만들 필요가 없습니다. 그리드의 ItemSource를 내 사용자 지정 개체에 설정하고 어떤 시점에서 런타임의 동적 그리드 열을 정의하려고합니다. 개체의 종류에 따라 달라집니다.

그럴 수 있습니까?

환호

답변

9

나는 어쩌면 일을 할 수있는 최선의 해결책이 아니라 말함으로써이 서문거야 어떤 상황에서 작동하지 않을 수 있습니다하지만 당신은 그것을 시도하고 그것을 위해 작동하는지 볼 수 있습니다 당신이 원하는. 나는 그걸 좀 채찍질하여 그 안에 약간의 버그가있을 수 있습니다. 아직 몇 가지 코드가 포함될 예정이지만 모델이보기에 대해 알지 못하게합니다.

DataGrid의 Columns 속성을 바인딩 할 수있는 확장 속성을 만들면됩니다. 다음은 제가 함께 모범을 보인 예입니다. 그런 다음

using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.Windows; 
using System.Windows.Controls; 

public static class DataGridExtension 
{ 
    public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject obj) 
    { 
     return (ObservableCollection<DataGridColumn>)obj.GetValue(ColumnsProperty); 
    } 

    public static void SetColumns(DependencyObject obj, ObservableCollection<DataGridColumn> value) 
    { 
     obj.SetValue(ColumnsProperty, value); 
    } 

    public static readonly DependencyProperty ColumnsProperty = 
      DependencyProperty.RegisterAttached("Columns", 
      typeof(ObservableCollection<DataGridColumn>), 
      typeof(DataGridExtension), 
      new UIPropertyMetadata (new ObservableCollection<DataGridColumn>(), 
      OnDataGridColumnsPropertyChanged)); 


    private static void OnDataGridColumnsPropertyChanged(
      DependencyObject d, 
      DependencyPropertyChangedEventArgs e) 
    { 
     if (d.GetType() == typeof(DataGrid)) 
     { 
      DataGrid myGrid = d as DataGrid; 

      ObservableCollection<DataGridColumn> Columns = 
       (ObservableCollection<DataGridColumn>)e.NewValue; 

      if(Columns != null) 
      { 
       myGrid.Columns.Clear(); 

       if (Columns != null && Columns.Count > 0) 
       { 
        foreach (DataGridColumn dataGridColumn in Columns) 
        { 
         myGrid.Columns.Add(dataGridColumn); 
        } 
       } 


       Columns.CollectionChanged += delegate(object sender, 
           NotifyCollectionChangedEventArgs args) 
        { 
         if(args.NewItems != null) 
         { 
         foreach (DataGridColumn column 
           in args.NewItems.Cast<DataGridColumn>()) 
         { 
          myGrid.Columns.Add(column); 
         } 
         } 

         if(args.OldItems != null) 
         { 
         foreach (DataGridColumn column 
           in args.OldItems.Cast<DataGridColumn>()) 
         { 
          myGrid.Columns.Remove(column); 
         } 
         } 
        }; 
      } 
     } 
    } 
} 

이 같은 데이터 그리드 당신에 부착 내가 당신 경우 응답 것입니다 얼마나 잘 모르겠어요

<Controls:DataGrid AutoGenerateColumns="False" 
      DataGridExtension.Columns="{Binding Columns}" /> 

(여기서 열은보기 모델에 ObservableCollection에 속성이다) 열 추가 및 제거를 시작하지만 기본 테스트에서 작동하는 것 같습니다. 행운을 빕니다!

+1

위 코드는 일반적으로 작업을 수행합니다. 그러나 DataGrid를 숨기고 다시 표시 할 때 실패합니다. columns 속성은 숨겨져 있고 columns 속성이 변경 될 때 0 열이 표시되므로 콜백이 실행되고 열을 다시 추가하려고 시도하지만 실제로 데이터 그 릿에 열이 있으므로 코드가 중복 열을 추가 할 수 없다는 예외가 있으면 실패합니다. –

1

비슷한 문제가있어서 다른 종속성 속성을 추가하고 싶지 않았습니다. 일시적인 해결책은 DataTable의 DataGrid에 표시 할 데이터를 구성하고이 DataTable에 DataGrid ItemSource 속성을 바인딩하는 것입니다 (물론 AutoGenerateColumns를 true로 설정).

DataGrids는 DataTable을 소스로 사용하는 것이 효과적입니다.

+0

DataGrid.ItemSource는 DataTable을 허용하지 않습니다. 그것은 IEnumerable ... (닷넷 4.5) –

+0

나는 4.5와 함께 프로젝트를 구축하고 그것은 내게 어떤 오류를주지 않았다. 나는 DataRow의 itemsource를 xaml에 바인딩합니다 :'ItemsSource = "{Binding ResultsViewerValues}", ResultsViewerValues는 뷰 모델의 속성 (DataTable)입니다. – user3189858