【问题标题】:Update dynamic column in datagrid更新数据网格中的动态列
【发布时间】:2013-09-08 04:58:25
【问题描述】:

我整天都在为此工作,但我陷入困境并且没有解决方案。看起来很简单..

我有一个包含动态列数的数据网格。每列都有一个带有 CellTemplate 和 CellEditingTemplate 的 DataGridTemplateColumn。 CellEditingTemplate 包含一个带有值的组合框,在用户选择一个值后,必须将 CellTemplate 中的 TextBox 更新为所选值。通常,您会将其绑定到对象中的已知属性,但由于我不知道用户提前需要多少列,因此我必须在运行时创建这些属性(或其他内容)并尝试绑定此文本框和组合框到这个属性。我该如何解决这个问题?我更喜欢不使用 ExpandoObjects 并且我受限于 .net 4.0

我的解决方案(还没有工作)是在每个行对象的列表/数组中添加一个包装对象,然后在代码中生成一个新的 DataGridTemplateColumn,其中组合框和文本框具有到数组中这个包装对象的数据绑定。在 XAML 中,这看起来像 ,但我无法将此 0 更改为 1,2,3,... 我可以在后面的代码中做到这一点,但我不知道如何将它绑定到 WrapperObjectList[X].Value?

这是一个简化的示例,希望有助于理解我想要实现的目标:

我有数据网格,它使用 RowObjects [rowobject 表示 1 行.. ;) ] 绑定到 observablecollection。第一列是固定的,因此它绑定到 RowObject 中的属性。

现在我必须在此之后添加动态数量的列。这取决于用户选择了多少项目(不在示例中,但您会明白这一点)。我用点击按钮替换了这个动作。

对于每一列,我创建一个包装对象并将其添加到 RowObject 中的另一个 observablecollection。这给了我一点灵活性,因为我事先不知道要添加多少列。这个 Wrapperobject 包含我需要显示的值。

此外,我需要将此 WrapperObject 绑定到我的组合框中的选择。因此,如果我编辑一行,我从组合框中选择一个值,然后必须在单元格模板的 TextBox 中显示(设置)这个选定的值。

示例代码:

后面的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        LoadData();


        this.DataContext = RowList;

    }

    private void LoadData()
    {
        RowList = new ObservableCollection<RowObject>();
        WrapperObject lWrapperObject1 = new WrapperObject();
        lWrapperObject1.Value = 1;
        WrapperObject lWrapperObject2 = new WrapperObject();
        lWrapperObject2.Value = 2;

        WrapperObject lWrapperObject3 = new WrapperObject();
        lWrapperObject3.Value = 3;
        WrapperObject lWrapperObject4 = new WrapperObject();
        lWrapperObject4.Value = 4;

        WrapperObject lWrapperObject6 = new WrapperObject();
        lWrapperObject6.Value = 6;
        WrapperObject lWrapperObject8 = new WrapperObject();
        lWrapperObject6.Value = 8;

        RowObject lRowObject1 = new RowObject();
        lRowObject1.RowObjectName = "RowObject1";
        lRowObject1.WrapperCollection.Add(lWrapperObject1);
        lRowObject1.WrapperCollection.Add(lWrapperObject2);
        lRowObject1.WrapperCollection.Add(lWrapperObject6);

        RowObject lRowObject2 = new RowObject();
        lRowObject2.RowObjectName = "RowObject2";
        lRowObject2.WrapperCollection.Add(lWrapperObject3);
        lRowObject2.WrapperCollection.Add(lWrapperObject4);
        lRowObject2.WrapperCollection.Add(lWrapperObject8);

        RowList.Add(lRowObject1);
        RowList.Add(lRowObject2);


    }

    public ObservableCollection<RowObject> RowList { get; set; }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        DataGridTemplateColumn lTemplateColumn = new DataGridTemplateColumn();
        lTemplateColumn.Header = "NewDynamicColumn";
        var lMyCellTemplate= (DataTemplate)Resources["myCellTemplate"];
        var lMyCellEditingTemplate = (DataTemplate)Resources["myCellEditingTemplate"];

        // Text="{Binding WrapperCollection[1].Value}" ????

        lTemplateColumn.CellTemplate =lMyCellTemplate;
        lTemplateColumn.CellEditingTemplate = lMyCellEditingTemplate;
        this.MyGrid.Columns.Add(lTemplateColumn);
    }
}

public class RowObject : INotifyPropertyChanged
{

    public RowObject()
    {
        WrapperCollection = new ObservableCollection<WrapperObject>();
        ComboBoxList = new List<string>();
        ComboBoxList.Add("10");
        ComboBoxList.Add("20"); 
    }

    public ObservableCollection<WrapperObject> WrapperCollection { get; set; }

    private string fRowObjectName;

    public string RowObjectName
    {
        get { return fRowObjectName; }
        set
        {
            fRowObjectName = value;
            RaisePropertyChanged("RowObjectName");
        }
    }

    public List<string> ComboBoxList { get; set; }

    #region Notify property changed
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

}

public class WrapperObject : INotifyPropertyChanged
{
    private int fValue;

    public int Value 
    { 
        get {return fValue;}
        set
        {
            fValue = value;
            RaisePropertyChanged("Value");
        }
    }

    #region Notify property changed
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

Xaml:

<Window.Resources>
    <DataTemplate x:Key="myCellTemplate">
        <TextBlock Text="{Binding WrapperCollection[1].Value}" />
    </DataTemplate>

    <DataTemplate x:Key="myCellEditingTemplate">
        <ComboBox ItemsSource="{Binding ComboBoxList}" />
    </DataTemplate>
</Window.Resources>

<StackPanel>
    <DataGrid   x:Name="MyGrid" 
                AutoGenerateColumns="False"
                ItemsSource="{Binding}"
                >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding RowObjectName}"/>
            <DataGridTextColumn Header="ExampleColumn1" Binding="{Binding WrapperCollection[0].Value}"/>
            <DataGridTemplateColumn Header="ExampleColumn2" CellTemplate="{StaticResource myCellTemplate}" CellEditingTemplate="{StaticResource myCellEditingTemplate}"/>           
        </DataGrid.Columns>
    </DataGrid>
    <Button Content="Click" Click="Button_Click" Width="100" Margin="20"/>
</StackPanel>

ExampleColumn1 和 ExampleColumn2 是此示例中唯一可编辑的列,单击按钮后,添加的列也可编辑。 现在我认为解决方案类似于在后面的代码中创建与 WrapperCollection[2].Value、WrapperCollection[3].Value 等的新绑定,但是如何?

【问题讨论】:

    标签: c# wpf data-binding datagrid combobox


    【解决方案1】:

    XAMLReader 救了我!现在我可以创建任何我想要的 DataTemplate..

        public DataTemplate CreateDataTemplate(Type type, int aNumber)
        {
            StringReader stringReader = new StringReader(
            @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""> 
            <" + type.Name + @" Text=""{Binding WrapperCollection[" + aNumber.ToString() + @"].Value}""/> 
        </DataTemplate>");
            XmlReader xmlReader = XmlReader.Create(stringReader);
            return XamlReader.Load(xmlReader) as DataTemplate;
        }
    
    {
        ...
        TextBlock textBlock = new TextBlock();
        var lMyCellTemplate = CreateDataTemplate(textBlock.GetType(), Counter);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-03
      • 2013-06-10
      • 2015-11-29
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多