gpt4 book ai didi

c# - 动态设置 DataGridColumn 的单元格内容

转载 作者:行者123 更新时间:2023-11-30 18:18:48 27 4
gpt4 key购买 nike

我正在 WPF MVVM 中创建动态 UI 应用程序,它将 UI 区域绑定(bind)到我的自定义 UIField 类的集合。

UIField 包含许多 BindingProperty 属性,允许我指定 Control 将绑定(bind)到的属性。

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>

然后我在 View 模型中创建这些字段并将它们添加到集合中。然后,UI 使用 ItemsControl

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

这对于普通字段非常有用,但我遇到了 DataGrid 的问题。

最好,我希望能够绑定(bind)已扩展的 UIField 集合,为 DataGrid 的列提供 Header 属性,然后绑定(bind)模板这些到 DataGridColumn,但您不能在 DataTemplate 中有 DataGridColumn

目前,我已经创建了一个界面,为我提供标题、DataGridColumn 类型和每个单元格中应包含的内容:

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

Type ColumnType { get; }

UIField CellContents { get; }
}

然后我使用以下方法将它们绑定(bind)到 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 中每个单元格的内容?

编辑 1(进度?):

我意识到生成的 DataGridColumn 必须是 DataGridTemplateColumn,因此这会打开更多属性。

我修改了 IDataGridField,将 UIField 属性更改为 Type

然后,在生成新的 DataGridColumn 时,我只获取分配给所选 TypeDataTemplate

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);
}

我认为现在唯一的问题是应用绑定(bind)。

最佳答案

看来你想重新发明轮子。 WPF DataGrid 已经很好地处理基本的数据类型,如字符串、 bool 、整数。但是您会有自己的理由。

我认为如果您想采用动态方法,您需要设置 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;
}
}

关于c# - 动态设置 DataGridColumn 的单元格内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40608915/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com