2016-11-15 1 views
3

UI의 영역을 내 사용자 지정 UIField 클래스의 컬렉션에 바인딩하는 동적 UI 응용 프로그램을 WPF MVVM에서 만듭니다.DataGridColumn의 셀 내용을 동적으로 설정합니다.

UIField에는 이 바인딩 할 속성을 지정할 수있는 BindingProperty 속성이 포함되어 있습니다.

public abstract class UIField : BaseObject 
{ 
    BindingProperty property, isReadonly = new BindingProperty(false, false); 
    object dataContext; 

    public BindingProperty Property 
    { 
     get { return property; } 
     set { SetProperty(ref property, value,() => Property); } 
    } 
    public BindingProperty IsReadonly 
    { 
     get { return isReadonly; } 
     set { SetProperty(ref isReadonly, value,() => IsReadonly); } 
    } 
    public object DataContext 
    { 
     get { return dataContext; } 
     set { SetProperty(ref dataContext, value,() => DataContext); } 
    } 
} 

ResourceDictionary에서 나는 UIField

<DataTemplate DataType="{x:Type fields:TextBoxField}"> 
    <TextBox metro:TextBoxHelper.Watermark="{e:IndirectBinding Watermark}" 
      metro:TextBoxHelper.UseFloatingWatermark="{e:IndirectBinding UseFloatingWatermark}" 
      IsReadOnly="{e:IndirectBinding IsReadonly}" 
      Text="{e:IndirectBinding Property}"     
       /> 
</DataTemplate> 

의 파생 클래스를 템플릿 그리고 난 다음 뷰 모델에서 이러한 필드를 만들고 컬렉션에 추가합니다. UI는 다음이 일반 필드에 큰 노력하지만 DataGrid에 문제가 실행 해요 ItemsControl

new TextBoxField() 
{ 
    DataContext = this, 
    Property = new BindingProperty(() => ((SalesOrder)Order).SecondSalesReference), 
    Watermark = new BindingProperty("Customer Ref. Number", false), 
    UseFloatingWatermark = new BindingProperty(true, false) 
} 

를 사용하여 컬렉션에 바인딩합니다.

바람직하게는, 나는 DataGrid의 컬럼에 머리글 속성을 제공하고 DataGridColumn들에 이러한 템플릿을 확장 한 UIField의 모음을 결합 할 수 있도록하고 싶습니다하지만 당신은 DataGridColumn에있을 수 없습니다 a DataTemplate.

public interface IDataGridField 
{ 
    string Header { get; set; } 

    Type ColumnType { get; } 

    UIField CellContents { get; } 
} 

그때 사용 DataGrid의 컬럼에 이러한 바인딩 :

현재, 나는 나에게 헤더, DataGridColumn 유형과 각 셀에 있어야 내용을 제공하는 인터페이스를 만들었습니다

public class DataGridHelper 
{ 
    public static readonly DependencyProperty BindableColumnsProperty = DependencyProperty.RegisterAttached("BindableColumns", typeof(ThreadSafeCollection<IDataGridField>), typeof(DataGridHelper),new UIPropertyMetadata(null, BindableColumnsPropertyChanged)); 
    static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     var dataGrid = source as DataGrid; 
     var columns = e.NewValue as ThreadSafeCollection<IDataGridField>; 
     dataGrid.Columns.Clear(); 
     if (columns == null) 
      return; 

     foreach (var column in columns) 
     { 
      var newColumn = Utility.CreateInstance(column.ColumnType) as DataGridColumn; 
      newColumn.Header = column.Header; 
      dataGrid.Columns.Add(newColumn); 
     } 
    } 
    public static void SetBindableColumns(DependencyObject element, ThreadSafeCollection<IDataGridField> value) 
    { 
     element.SetValue(BindableColumnsProperty, value); 
    } 
    public static ThreadSafeCollection<IDataGridField> GetBindableColumns(DependencyObject element) 
    { 
     return (ThreadSafeCollection<IDataGridField>)element.GetValue(BindableColumnsProperty); 
    } 
} 

이렇게하면 DataGridCell에 헤더가있는 열은 있지만 내용은 표시되지 않습니다.

DataGridColumn에서 각 셀의 내용을 어떻게 설정합니까?

EDIT 1 (진행은?) :

내가 생성 된 DataGridColumnDataGridTemplateColumn 수있다 그래서 이것은 몇 속성을 열어 것을 깨달았다.

IDataGridField을 수정했으며 UIField 속성을 Type으로 변경했습니다. 새로운 DataGridColumn를 생성 할 때

그럼, 난 그냥 DataTemplate 내가 유일한 문제는 이제 바인딩을 적용 생각 선택한 Type

foreach (var column in columns) 
{ 
    var newColumn = new DataGridTemplateColumn(); 
    var key = new DataTemplateKey(column.CellContentType); 
    var template = Application.Current.FindResource(key) as DataTemplate; 
    newColumn.CellTemplate = template; 
    newColumn.Header = column.Header; 
    dataGrid.Columns.Add(newColumn); 
} 

에 할당받을.

답변

0

당신은 바퀴를 재발 명하고 싶습니다. WPF DataGrid는 string, bool, int와 같은 기본 DataTypes를 이미 잘 처리합니다. 그러나 이유는 분명히 있습니다.

"올바른"열 유형을 만드는 대신 CellTemplate 또는 CellEditingTemplate을 설정하려는 동적 접근 방식으로 가고 싶다고 생각합니다.이것은 더 복잡한 데이터 유형에도 적용됩니다.

이 바로 XAML하지만 당신이 갈 수있는 방향을 표시해야합니다

<DataGrid ItemsSource="{Binding}"> 
    <DataGrid.Columns> 
     <DataGridTemplateColumn> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
         <TextBox metro:TextBoxHelper.Watermark="{e:IndirectBinding Watermark}" 
      metro:TextBoxHelper.UseFloatingWatermark="{e:IndirectBinding UseFloatingWatermark}" 
      IsReadOnly="{e:IndirectBinding IsReadonly}" 
      Text="{e:IndirectBinding Property}"     
       /> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
    </DataGrid.Columns> 
</DataGrid> 

당신은 또한 열 생성을 대체 할 데이터 그리드의 AutoGeneratingColumn 이벤트를 사용할 수 있습니다. 어쩌면 당신은 CustomDataGrid를 파생시키고 싶습니까?

private void DataGrid_AutoGeneratingColumn(object sender, System.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e) 
{ 
    //check for the type 
    if (e.PropertyType == typeof(TextField)) 
    { 
     DataGridTemplateColumn newDataGridTemplateColumn = new DataGridTemplateColumn(); 
     e.Column = newDataGridTemplateColumn; 

     //do some datatemplate voodoo, maybe you want to load it from resources or similar 
     StringReader stringReader = new StringReader(
@"<DataTemplate 
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> 
    <" + typeof(ComboBox).Name + @" Text=""{Binding " + "Text" + @"}""/> 
</DataTemplate>"); 
     XmlReader xmlReader = XmlReader.Create(stringReader); 
     DataTemplate template = XamlReader.Load(xmlReader) as DataTemplate; 

     newDataGridTemplateColumn.CellTemplate = template; 
    } 
} 
+0

이 문제점은 동일한 유형의 동일한 DataTemplate을 제공한다는 점입니다. 다른 속성 (IsReadonly 등)을 지정할 수 있어야합니다. 내 최선의 방법은 DataGridTemplateColumn 및 GenerateElement()를 재정의 할 수 있다고 생각합니다. – Blinx

관련 문제