Я создаю динамическое приложение пользовательского интерфейса в WPF MVVM, которое связывает области пользовательского интерфейса с коллекцией моего настраиваемого класса UIField
.Динамически установить содержимое ячейки DataGridColumn
UIField
содержит ряд объектов BindingProperty
, которые позволяют мне указать свойство, которое свяжет Control
.
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
I шаблон производных классов 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 затем связывается с коллекцией с помощью ItemsControl
new TextBoxField()
{
DataContext = this,
Property = new BindingProperty(() => ((SalesOrder)Order).SecondSalesReference),
Watermark = new BindingProperty("Customer Ref. Number", false),
UseFloatingWatermark = new BindingProperty(true, false)
}
Это работает отлично подходит для нормальных полей, но я бегу в проблему с DataGrid
.
Предпочтительно, я хотел бы быть в состоянии связать коллекцию UIField
с, которые были продлены, чтобы обеспечить свойство заголовка для столбцов DataGrid
, а затем шаблон их к DataGridColumn
с, но вы не можете иметь DataGridColumn
в a DataTemplate
.
В настоящее время я создал интерфейс, который дает мне заголовок, DataGridColumn
типа и содержимое, которое должно быть в каждой клетке:
public interface IDataGridField
{
string Header { get; set; }
Type ColumnType { get; }
UIField CellContents { get; }
}
Я тогда связываю этот друг DataGrid
сек столбцов с помощью:
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 (Progress):
я понял, что DataGridColumn
генерироваться должен быть DataGridTemplateColumn
так это открывает несколько дополнительных свойств.
Я изменил 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);
}
Я думаю, что единственная проблема сейчас применяют привязки.
Проблема в том, что это даст мне тот же DataTemplate для одного и того же типа. Мне нужно указать разные свойства (IsReadonly и т. Д.). Я думаю, что мой лучший выбор может быть переопределением DataGridTemplateColumn и GenerateElement() – Blinx