Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时为动态创建的对象动态创建绑定_C#_Wpf_Xaml_Mvvm_Dynamic - Fatal编程技术网

C# 在运行时为动态创建的对象动态创建绑定

C# 在运行时为动态创建的对象动态创建绑定,c#,wpf,xaml,mvvm,dynamic,C#,Wpf,Xaml,Mvvm,Dynamic,我试图创建一个Datagrid矩阵,在运行时添加带有绑定的列 我在VisualStudio2019工作,与C#、WPF和MVVM一起工作 矩阵如下所示: <DataGridTextColumn Header="Name" Binding="{Binding EntryName, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn> <DataGrid Name="MyGrid" ItemsSourc

我试图创建一个Datagrid矩阵,在运行时添加带有绑定的列

我在VisualStudio2019工作,与C#、WPF和MVVM一起工作

矩阵如下所示:

<DataGridTextColumn Header="Name" Binding="{Binding EntryName, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>
<DataGrid Name="MyGrid" ItemsSource="{Binding ProceduresTable }"  SelectionMode="Single" SelectedItem="{Binding SelectedEntryProcedures}" AutoGenerateColumns="false" CanUserAddRows="True" IsReadOnly="False" >

前三行是在视图的.xaml中创建的,而最后两列是动态创建的。在另一个视图中,有一个类似的datagrid,其中添加的每一行都会在该矩阵中产生一列

通常的列是这样创建的:

<DataGridTextColumn Header="Name" Binding="{Binding EntryName, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>
<DataGrid Name="MyGrid" ItemsSource="{Binding ProceduresTable }"  SelectionMode="Single" SelectedItem="{Binding SelectedEntryProcedures}" AutoGenerateColumns="false" CanUserAddRows="True" IsReadOnly="False" >
由于新列是动态添加的,我不确定如何创建动态绑定。当我使用一个数组时,我必须定义它的长度,当我尝试使用一个列表或一个ObservableCollection时,由于其他情况,我失败了

我需要对应行中复选框的信息。我已经通过表示整个DataGrid的ObservableCollection获得了单击哪一行的信息

我尝试的是:

            foreach(IControlRoleViewModel item in vm.ControlRoleTable)
        {
            if (item.EntryName != null) 
            {

                _newEntry = item.EntryName + "_IsTrue";

                //send Binding Definition to ViewModel
                vm.newEntry.Add(_newEntry); //vm.newEntry is a List<string> in the ViewModel

                MyGrid.Columns.Add(new DataGridCheckBoxColumn { Header = item.EntryName, Binding = new Binding(_newEntry) }); 
            }
        }
foreach(vm.ControlRoleTable中的IControleviewModel项)
{
if(item.EntryName!=null)
{
_newEntry=item.EntryName+“\u IsTrue”;
//将绑定定义发送到ViewModel
vm.newEntry.Add(_newEntry);//vm.newEntry是ViewModel中的一个列表
添加(新DataGridCheckBoxColumn{Header=item.EntryName,Binding=newbinding(_newEntry)});
}
}
通过这种方式,我将新绑定的信息获取到ViewModel中。但由于代表整个矩阵的DataGrid定义如下:

<DataGridTextColumn Header="Name" Binding="{Binding EntryName, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>
<DataGrid Name="MyGrid" ItemsSource="{Binding ProceduresTable }"  SelectionMode="Single" SelectedItem="{Binding SelectedEntryProcedures}" AutoGenerateColumns="false" CanUserAddRows="True" IsReadOnly="False" >

ObservableCollection过程可重新启动的内部找不到绑定

之后,我尝试在IProceduresTable接口内创建一个新的ObservableCollection。但这失败了,因为我无法找到如何将绑定放入ObservableCollection中,而ObservableCollection本身就在ObservableCollection中


有更简单的方法吗?

对于这种情况,我使用GenericRow和GenericTable类:

您可以使用这两个类来创建动态行和列。使用GenericRow类,可以生成具有所需属性名称的行,也可以为列使用相同的属性名称进行适当的绑定

public class GenericRow : CustomTypeDescriptor, INotifyPropertyChanged
{

    #region Private Fields
    List<PropertyDescriptor> _property_list = new List<PropertyDescriptor>();
    #endregion

    #region INotifyPropertyChange Implementation

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChange Implementation

    #region Public Methods

    public void SetPropertyValue<T>(string propertyName, T propertyValue)
    {
        var properties = this.GetProperties()
                                .Cast<PropertyDescriptor>()
                                .Where(prop => prop.Name.Equals(propertyName));

        if (properties == null || properties.Count() != 1)
        {
            throw new Exception("The property doesn't exist.");
        }

        var property = properties.First();
        property.SetValue(this, propertyValue);

        OnPropertyChanged(propertyName);
    }

    public T GetPropertyValue<T>(string propertyName)
    {
        var properties = this.GetProperties()
                            .Cast<PropertyDescriptor>()
                            .Where(prop => prop.Name.Equals(propertyName));

        if (properties == null || properties.Count() != 1)
        {
            throw new Exception("The property doesn't exist.");
        }

        var property = properties.First();
        return (T)property.GetValue(this);
    }

    public void AddProperty<T, U>(string propertyName) where U : GenericRow
    {
        var customProperty =
                new CustomPropertyDescriptor<T>(
                                        propertyName,
                                        typeof(U));

        _property_list.Add(customProperty);
    }

    #endregion

    #region Overriden Methods

    public override PropertyDescriptorCollection GetProperties()
    {
        var properties = base.GetProperties();
        return new PropertyDescriptorCollection(
                            properties.Cast<PropertyDescriptor>()
                                      .Concat(_property_list).ToArray());
    }

    #endregion

}
公共类GenericRow:CustomTypeDescriptor,INotifyPropertyChanged
{
#区域专用字段
列表_属性_列表=新列表();
#端区
#区域INotifyPropertyChange实现
公共事件PropertyChangedEventHandler PropertyChanged=委托{};
受保护的无效OnPropertyChanged(字符串propertyName)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChange实现
#区域公共方法
public void SetPropertyValue(字符串propertyName,T propertyValue)
{
var properties=this.GetProperties()
.Cast()
其中(prop=>prop.Name.Equals(propertyName));
if(properties==null | | properties.Count()!=1)
{
抛出新异常(“属性不存在”);
}
var property=properties.First();
SetValue(这是propertyValue);
OnPropertyChanged(propertyName);
}
公共T GetPropertyValue(字符串propertyName)
{
var properties=this.GetProperties()
.Cast()
其中(prop=>prop.Name.Equals(propertyName));
if(properties==null | | properties.Count()!=1)
{
抛出新异常(“属性不存在”);
}
var property=properties.First();
return(T)property.GetValue(this);
}
公共void AddProperty(字符串propertyName),其中U:GenericRow
{
var自定义属性=
新CustomPropertyDescriptor(
propertyName,
(U)型;
_属性列表。添加(customProperty);
}
#端区
#区域覆盖方法
公共重写PropertyDescriptorCollection GetProperties()
{
var properties=base.GetProperties();
返回新属性DescriptorCollection(
properties.Cast()
.Concat(_property_list).ToArray();
}
#端区
}
和通用表:

public class GenericTable
{

    private string tableName = "";
    public string TableName
    {
        get { return tableName; }
        set { tableName = value; }
    }

    private ObservableCollection<DataGridColumn> columnCollection;
    public ObservableCollection<DataGridColumn> ColumnCollection
    {
        get { return columnCollection; }
        private set { columnCollection = value; }
    }

    private ObservableCollection<GenericRow> genericRowCollection;
    public ObservableCollection<GenericRow> GenericRowCollection
    {
        get { return genericRowCollection; }
        set { genericRowCollection = value; }
    }




    public GenericTable(string tableName)
    {
        this.TableName = tableName;
        ColumnCollection = new ObservableCollection<DataGridColumn>();
        GenericRowCollection = new ObservableCollection<GenericRow>(); 
    }

    /// <summary>
    /// ColumnName is also binding property name
    /// </summary>
    /// <param name="columnName"></param>
    public void AddColumn(string columnName)
    {
        DataGridTextColumn column = new DataGridTextColumn();
        column.Header = columnName;
        column.Binding = new Binding(columnName);
        ColumnCollection.Add(column);
    }



    public override string ToString()
    {
        return TableName; 
    }


}
公共类可泛化
{
私有字符串tableName=“”;
公共字符串表名
{
获取{return tableName;}
设置{tableName=value;}
}
私人可观测集合;
公共可观测集合列集合
{
获取{return columnCollection;}
私有集{columnCollection=value;}
}
私有可观测集合一般微集合;
公共可观测集合一般微集合
{
获取{return genericRowCollection;}
设置{genericRowCollection=value;}
}
公共通用表(字符串表名)
{
this.TableName=TableName;
ColumnCollection=新的ObservableCollection();
GenericRowCollection=新的ObservableCollection();
}
/// 
///ColumnName也是绑定属性名
/// 
/// 
public void AddColumn(字符串columnName)
{
DataGridTextColumn=新DataGridTextColumn();
column.Header=columnName;
column.Binding=新绑定(columnName);
ColumnCollection.Add(column);
}
公共重写字符串ToString()
{
返回表名;
}
}
对于XAML方面:

    <DataGrid Name="dataGrid"
              local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
              AutoGenerateColumns="False"
              ...>

最后是DataGridColumsBehaior:

public class DataGridColumnsBehavior
{
    public static readonly DependencyProperty BindableColumnsProperty =
        DependencyProperty.RegisterAttached("BindableColumns",
                                            typeof(ObservableCollection<DataGridColumn>),
                                            typeof(DataGridColumnsBehavior),
                                            new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
    private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        DataGrid dataGrid = source as DataGrid;
        ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
        dataGrid.Columns.Clear();
        if (columns == null)
        {
            return;
        }
        foreach (DataGridColumn column in columns)
        {
            dataGrid.Columns.Add(column);
        }
        columns.CollectionChanged += (sender, e2) =>
        {
            NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
            if (ne.Action == NotifyCollectionChangedAction.Reset)
            {
                dataGrid.Columns.Clear();
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataGridColumn column in ne.NewItems)
                {
                    dataGrid.Columns.Add(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Move)
            {
                dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
            }
            else if (ne.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (DataGridColumn column in ne.OldItems)
                {
                    dataGrid.Columns.Remove(column);
                }
            }
            else if (ne.Action == NotifyCollectionChangedAction.Replace)
            {
                dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
            }
        };
    }
    public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
    {
        element.SetValue(BindableColumnsProperty, value);
    }
    public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
    {
        return (ObservableCollection<DataGridColumn>)element.GetValue(BindableColumnsProperty);
    }
}
公共类DataGridColumnsBehavior
{
公共静态只读从属属性BindableColumnsProperty=
DependencyProperty.RegisterA