• DataGrid中动态添加列


         最近在项目中碰到了这样一个场景:DataGrid需要绑定到一个ObservableCollection<MyClass>,MyClass包含了一组对象,每个对象对应DataGrid的一个Column,如果把这一组对象放进MyClass的一个ObservableCollection<>属性中,则无法绑定;如果每个对象做为MyClass的一个属性,则可以动态创建Column并绑定到属性。因此我们需要能为MyClass动态添加属性,使用dynamic类型是个不错的选择。实现步骤如下:

       1、  首先定义属性

            public ObservableCollection<dynamic> DisplayPlanList {get;set;}

            并绑定到DataGrid,PlanGrid.ItemsSource = DisplayPlanList;

       2、 定义一个DynamicObject类

    public class DynamicObjectClass : DynamicObject, INotifyPropertyChanged
    {
    #region DynamicObject overrides

    public DynamicObjectClass()
    {
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
    return members.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
    members[binder.Name] = value;
    OnPropertyChanged(binder.Name);
    return true;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
    return members.Keys;
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
    int index = (int)indexes[0];
    try
    {
    result = itemsCollection[index];
    }
    catch (ArgumentOutOfRangeException)
    {
    result = null;
    return false;
    }
    return true;
    }

    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
    {
    int index = (int)indexes[0];
    itemsCollection[index] = value;
    OnPropertyChanged(System.Windows.Data.Binding.IndexerName);
    return true;
    }

    public override bool TryDeleteMember(DeleteMemberBinder binder)
    {
    if (members.ContainsKey(binder.Name))
    {
    members.Remove(binder.Name);
    return true;
    }
    return false;
    }

    public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes)
    {
    int index = (int)indexes[0];
    itemsCollection.RemoveAt(index);
    return true;
    }

    #endregion DynamicObject overrides

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
    if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged

    #region Public methods

    public object AddItem(object item)
    {
    itemsCollection.Add(item);
    OnPropertyChanged(Binding.IndexerName);
    return null;
    }

    #endregion Public methods

    #region Private data

    Dictionary<string, object> members = new Dictionary<string, object>();
    ObservableCollection<object> itemsCollection = new ObservableCollection<object>();

    #endregion Private data
    }


    public class SetPropertyBinder : SetMemberBinder
    {
    public SetPropertyBinder(string propertyName)
    : base(propertyName, false) { }

    public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
    {
    return new DynamicMetaObject(
    System.Linq.Expressions.Expression.Throw(
    System.Linq.Expressions.Expression.New(
    typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) }),
    new System.Linq.Expressions.Expression[] { System.Linq.Expressions.Expression.Constant("Error") }),
    this.ReturnType), BindingRestrictions.Empty);
    }
    }

    public class GetPropertyBinder : GetMemberBinder
    {
    public GetPropertyBinder(string propertyName)
    : base(propertyName, false) { }

    public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject value)
    {
    return new DynamicMetaObject(
    System.Linq.Expressions.Expression.Throw(
    System.Linq.Expressions.Expression.New(
    typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) }),
    new System.Linq.Expressions.Expression[] { System.Linq.Expressions.Expression.Constant("Error") }),
    this.ReturnType), BindingRestrictions.Empty);
    }
    }

    该类继承自DynamicObject,主要提供了设置属性、获取属性功能。

    3、 为DataGrid动态添加列

    dynamic item = new DynamicObjectClass();
    item.ID = Guid.NewGuid();
    item.Name = "名称#";
    ObjectList.Add(item);
    PlanGrid.Columns.Add(new DataGridTextColumn() { Header = "编号", Binding = new Binding("ID") });
    PlanGrid.Columns.Add(new DataGridTextColumn() { Header = "名称", Binding = new Binding("Name") });

    上面代码中的ID、Name是硬编码设置的属性,也可以根据参数动态设置属性,如下:

    foreach (DynamicObjectClass obj in ObjectList)
    {
    obj.TrySetMember(new SetPropertyBinder(propName), bindingData);
    }

    上面代码的意思是为每个DynamicObject添加一个名为propName的属性,并绑定到bindingData对象。其中每个DynamicObject对应DataGrid的一行,propName对应DataGrid

    的一列,可按如下方式为DataGrid添加一列:

    DataGridTextColumn column = new DataGridTextColumn();

    string propName = "New Column";

    column.Binding = new Binding(propName);

    PlanGrid.Columns.Add(column);

    如果需要可通过以下方式获取某个属性对应的绑定值:

    object ID;
    obj.TryGetMember(new GetPropertyBinder("ID"), out ID);


    以上实现方式参考了网上若干资料,具体网址没有保存下来,无法提供链接,希望原作者见谅!





  • 相关阅读:
    H5 标签属性、input属性
    使用Hexo搭建个人博客配置全过程
    vue iView 打包后 字体图标不显示
    webpack 打包后 Uncaught SyntaxError: Unexpected token <
    node 搭建本地服务器
    csf 课件转化为wmv正常格式
    css+background实现 图片宽高自适应,拉伸裁剪不变形
    PHP访问时Forbidden403错误
    jQuery事件对象
    JS获取当前时间实时显示
  • 原文地址:https://www.cnblogs.com/wenjingu/p/2296183.html
Copyright © 2020-2023  润新知