gpt4 book ai didi

c# - 将数据网格列绑定(bind)到动态属性

转载 作者:行者123 更新时间:2023-11-30 16:58:53 25 4
gpt4 key购买 nike

我正在处理一项要求,其中可以将任意数量的动态属性添加到实体中。除了实际的对象属性之外,这些动态属性还可以显示在数据网格列中。

为了尊重现有架构,这些属性存储在列表中:

public List<AdaErgaenzungsfeldEntity> Ergaenzungsfelder { get; set; }

为了绑定(bind)到列表中的每个属性,我公开了将在网格中显示的值,如下所示:

public Dictionary<Guid, object> ErgaenzungsfeldValues { 
get { return m_ergaenzungsfeldValues; }
}

当 Ergaenzungsfelder 列表更改时,列表和字典正在同步:

private void RefreshErgaenzungsfeldValues() {
if (m_ergaenzungsfeldValues == null) {
m_ergaenzungsfeldValues = new Dictionary<Guid, object>();
}

m_ergaenzungsfeldValues.Clear();
foreach (AdaErgaenzungsfeldEntity entity in Ergaenzungsfelder) {
m_ergaenzungsfeldValues.Add(entity.Ergaenzungsfeld.ID, entity.Value);
}
}

到网格的绑定(bind)最终是这样完成的:

List<ErgaenzungsfeldEntity> ergaenzungsfeldEntities = m_presenter.ErgaenzungsfeldService.GetAllErgaenzungsfeldEntities();
foreach (ErgaenzungsfeldEntity entity in ergaenzungsfeldEntities) {
m_lstAdas.Columns.Add(new Column {
Title = entity.Name,
FieldName = string.Format("ErgaenzungsfeldValues[{0}]", entity.ID)
});
}

此实现的问题是字典不包含所有实体的所有动态字段的值,这显然会导致找不到键异常:

System.Windows.Data Error: 16 : Cannot get 'Item[]' value (type 'Object') from 'ErgaenzungsfeldValues' (type 'Dictionary2').
BindingExpression:Path=ErgaenzungsfeldValues[04d1be1c-2d83-48ba-b179-aaa9f0d0f7bc];
DataItem='AdaEntity' (HashCode=-800079524); target element is
'DataCell' (Name=''); target property is 'Content' (type 'Object')
TargetInvocationException:'System.Reflection.TargetInvocationException:
Exception has been thrown by the target of an invocation. --->
System.Collections.Generic.KeyNotFoundException: The given key was not
present in the dictionary. at
System.ThrowHelper.ThrowKeyNotFoundException() at
System.Collections.Generic.Dictionary
2.get_Item(TKey key) --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level) at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'

实体不知道所有可能的字段,因此不可能为每个实体的每个动态属性添加默认值。

问题如何将这些动态值正确绑定(bind)到数据网格以避免上述异常?

我创建了一个小应用程序来说明该行为。

主窗口.xaml:

<Window x:Class="DynamicdataGridBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<xcdg:DataGridControl
Name="m_dataGridControl"
AutoCreateColumns="False"
AutoRemoveColumnsAndDetailConfigurations="False"
ReadOnly="True"
ItemsSource="{Binding TestEntities}">
<xcdg:DataGridControl.Columns>
<xcdg:Column Title="Property"
FieldName="DefinedProperty" />
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
</Window>

主窗口.xaml.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xceed.Wpf.DataGrid;

namespace DynamicdataGridBindingTest {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow {
private readonly Dictionary<Guid, string> m_dynamicColumnNames = new Dictionary<Guid, string> {
{Guid.NewGuid(),"DynText"},
{Guid.NewGuid(),"DynBool"},
{Guid.NewGuid(),"DynArray"}
};

public ObservableCollection<TestEntity> TestEntities { get; private set; }

public MainWindow() {
//Licenser.LicenseKey = "xxx";
TestEntities = new ObservableCollection<TestEntity>();

InitializeComponent();
InitializeEntities();
InitializedataGridColumns();
}


private void InitializeEntities() {
TestEntity testEntity1 = new TestEntity {
DefinedProperty = "Property Value 1",
};
testEntity1.DynamicProperties.Add(m_dynamicColumnNames.ElementAt(0).Key, "My text");
testEntity1.DynamicProperties.Add(m_dynamicColumnNames.ElementAt(1).Key, true);
testEntity1.DynamicProperties.Add(m_dynamicColumnNames.ElementAt(2).Key, new[] { "val1.1", "val1.2", "val1.3" });
TestEntities.Add(testEntity1);

TestEntity testEntity2 = new TestEntity {
DefinedProperty = "Property Value 2"
};
testEntity2.DynamicProperties.Add(m_dynamicColumnNames.ElementAt(0).Key, "My text 2");
TestEntities.Add(testEntity2);
}

private void InitializedataGridColumns() {
foreach (string columnName in m_dynamicColumnNames.Values) {
m_dataGridControl.Columns.Add(new Column {
Title = columnName,
FieldName = string.Format("DynamicProperties[{0}]", m_dynamicColumnNames.First(kv => kv.Value == columnName).Key)
});
}
}
}
}

测试实体.cs:

namespace DynamicdataGridBindingTest {

public class TestEntity {
public string DefinedProperty { get; set; }
public Dictionary<Guid, object> DynamicProperties { get; private set; }

public TestEntity() {
DynamicProperties = new Dictionary<Guid, object>();
}
}
}

运行时看起来像这样: enter image description here

最佳答案

我通过实现一个最小的 Dictionary 实现解决了这个问题,包装了一个 Dictionary,但没有抛出 key not found 异常:

using System.Collections.Generic;

namespace DynamicdataGridBindingTest {
/// <summary>
/// This is a minimal implementation of a Dictionary, which will never throw KeyNotFoundException if trying to access a value for a key which hasn't been set.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
public class DictionaryWithReturnValue<TKey, TValue> {
#region Private Fields

private readonly Dictionary<TKey, TValue> m_dictionary;

#endregion

#region Constructor

/// <summary>
/// Initializes a new instance of the <see cref="DictionaryWithReturnValue{TKey, TValue}"/> class.
/// </summary>
public DictionaryWithReturnValue() {
m_dictionary = new Dictionary<TKey, TValue>();
}

#endregion

#region Indexer

/// <summary>
/// Gets or sets the value for the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>The value, if it has been previously set; otherwise default(TValue)</returns>
public TValue this[TKey key] {
get {
TValue value;
return m_dictionary.TryGetValue(key, out value) ? value : default(TValue);
}
set { m_dictionary[key] = value; }
}

#endregion

#region Public Methods

/// <summary>
/// Adds the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public void Add(TKey key, TValue value) {
m_dictionary.Add(key, value);
}

/// <summary>
/// Removes the specified key.
/// </summary>
/// <param name="key">The key.</param>
public void Remove(TKey key) {
m_dictionary.Remove(key);
}

/// <summary>
/// Clears all the entries.
/// </summary>
public void Clear() {
m_dictionary.Clear();
}

#endregion
}
}

关于c# - 将数据网格列绑定(bind)到动态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24573614/

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