如何将Wpf DataGridColumn绑定到对象?

时间:2009-05-19 17:16:49

标签: wpf datagrid

我想将WPF DataGrid的列绑定到Dictionary中的某些对象,如下所示:

绑定路径=对象[i]

其中Objects是我的对象字典,因此每个单元格都代表一个Object元素。我怎么能这样做?

我想我需要为我的单元格创建一个模板,我做了,但如何在模板中获取列绑定的结果?我知道默认情况下,DataGridCell的内容是一个TextBlock,它的Text属性是通过列绑定结果设置的,但如果该结果是一个对象,我想我必须创建一个ContentTemplate。我怎么做,因为我尝试的东西没有显示任何东西。

这是我试过的:

<Style x:Key="CellStyle" TargetType="{x:Type dg:DataGridCell}">
    <Setter Property="Template"> ---it should realy be ContentTemplate?
      <Setter.Value>
        <ControlTemplate>
          <controls:DataGridCellControl CurrentObject="{Binding }"/> -- I would expect to get the object like this for this column path : Path=Objects[i] but is not working
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

所以,为了让自己完全清楚,我想在我的DataGridCellControl的CurrentObject属性中获取当我在数据网格中设置列绑定时应该产生的当前对象,如Path = Objects [i]。

感谢您的任何建议,

约翰。

2 个答案:

答案 0 :(得分:0)

试试这个:

<ListView x:Name="listViewUsers" SelectionMode="Single" 
                              ItemsSource="{Binding ElementName=window1, Path=Users, Mode=TwoWay}" MouseDoubleClick="listViewUsers_MouseDoubleClick">
                        <ListView.View>
                            <GridView x:Name="gridViewUsers" AllowsColumnReorder="False">
                                <GridViewColumn>
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <Image Source="{Binding Path=IsAdministrator, Converter={StaticResource boolToImage}, ConverterParameter='Images/admin18.gif|Images/user18.gif'}" />
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                                <GridViewColumn Header="User Name" DisplayMemberBinding="{Binding Path=UserName}" Width="140" />
                                <GridViewColumn Header="Full Name" DisplayMemberBinding="{Binding Path=FullName}" Width="140" />
                                <GridViewColumn Header="Phone Number" DisplayMemberBinding="{Binding Path=PhoneNumber}" Width="110" />
                                <GridViewColumn Header="Access Type" DisplayMemberBinding="{Binding Path=AccessType}" Width="110">
                                </GridViewColumn>
                                <GridViewColumn>
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <Image Cursor="Hand" ToolTip="Delete User" Stretch="None" Source="Images/trash12.gif" MouseUp="DeleteUser" />
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                            </GridView>
                        </ListView.View>
                    </ListView>

ItemsSource中的位置=“{Binding ElementName = window1,Path = Users,Mode = TwoWay}”

  • ElementName是XAML中窗口的名称(只需将x:Name =“window1”添加到Window标记中,与任何其他控件一样。

  • 用户是一个List,应该与Dictionary

  • 一样
  • Mode = TwoWay意味着如果网格被修改,列表也会被修改,反之亦然(双向绑定)

修改

试试这个:

XAML:

<ListView x:Name="listViewTest" ItemsSource="{Binding}">
<ListView.View>
    <GridView x:Name="gridViewTest">

    </GridView>
</ListView.View>
</ListView>

C#:

public class TheClass
    {
        public int Col1, Col2, Col3; 
        public Dictionary<int, OtherColumns> otherColumns = new Dictionary<int,OtherColumns>();
    }

    public class OtherColumns
    {
        public string ColumnName;
        public int Value;
    }

在Window_Loaded:

下调用此方法
private void PopulateListView()
        {
            TheClass c = new TheClass();

            c.Col1 = 10;
            c.Col2 = 20;
            c.Col3 = 30;


            c.otherColumns.Add(0, new OtherColumns() { ColumnName = "Col4", Value = 40 });
            c.otherColumns.Add(1, new OtherColumns() { ColumnName = "Col5", Value = 50 });
            c.otherColumns.Add(3, new OtherColumns() { ColumnName = "Col6", Value = 60 });

            DataTable table = new DataTable();

// adding regular columns
            table.Columns.Add("Col1", typeof(int));
            table.Columns.Add("Col2", typeof(int));
            table.Columns.Add("Col3", typeof(int));

// adding dynamic columns
            foreach (KeyValuePair<int, OtherColumns> pair in c.otherColumns)
            {
                table.Columns.Add(pair.Value.ColumnName, typeof(int));
            }

            DataRow row = table.NewRow();

// adding regular column values to the DataTable
            row["Col1"] = c.Col1;
            row["Col2"] = c.Col2;
            row["Col3"] = c.Col3;

// adding dynamic column values to the DataTable
            foreach (KeyValuePair<int, OtherColumns> pair in c.otherColumns)
            {
                row[pair.Value.ColumnName] = pair.Value.Value;
            }

            table.Rows.Add(row);

            // Start binding the table.
            gridViewTest.Columns.Clear();

            System.Windows.Controls.GridViewColumn gvc;
            Binding binding;

            foreach (DataColumn column in table.Columns)
            {
                gvc = new System.Windows.Controls.GridViewColumn();
                binding = new System.Windows.Data.Binding();
                binding.Path = new PropertyPath(column.ColumnName);
                binding.Mode = BindingMode.OneWay;
                gvc.Header = column.Caption;
                gvc.DisplayMemberBinding = binding;
                gridViewTest.Columns.Add(gvc);
            }

            listViewTest.DataContext = table;
        }

我不是说这是最好的解决方案,但它可以提供帮助。让我知道。

答案 1 :(得分:0)

我创建了一些辅助类,因此我可以将DataGrid用作一种DataTable。换句话说,我想要DataGrid的格式化,排序和抛光外观,而不必事先预先制作一些类。我想要的主要原因是测试套件,我希望能够在运行时创建任意数量的列。这就是我得到的

public class DataRow
{
    internal List<object> Items = new List<object>();

    public object this[string value]
    {
        get { return Items[Convert.ToInt32(value)]; }
    }

    public string GetString(int index)
    {
        return Items[index].ToString();
    }

    public object GetObject(int index)
    {
        return Items[index];
    }

    public DataRow(params object[] values)
    {
        if (values == null || values.Length < 1)
            throw new Exception("You must pass in some values");

        Items.AddRange(values);            
    }
}  

public class GridConstructor
{
    public List<DataRow> Rows = new List<DataRow>();
    private DataRow headers;

    public GridConstructor(DataRow head)
    {
        headers = head;
    }

    public void BuildInto(DataGrid grid)
    {
        grid.AutoGenerateColumns = false;
        grid.Columns.Clear();
        int totalCols = 0;

        Type headType = headers.GetType();

        for (int i = 0; i < headers.Items.Count; i++)
        {
            grid.Columns.Add(GetCol(headers.GetString(i), String.Concat("[", i.ToString(),"]")));
            totalCols++;
        }                     

        int finalWidth = totalCols * (int)grid.ColumnWidth.Value + 15;
        grid.Width = finalWidth;

        grid.ItemsSource = Rows;
    }

    private DataGridTextColumn GetCol(string header, string binding)
    {
        DataGridTextColumn col = new DataGridTextColumn();
        col.IsReadOnly = true;            
        col.Header = header;
        col.Binding = new Binding(binding);

        return col;
    }

    public DataGrid Create(int colSize)
    {
        DataGrid grid = new DataGrid();
        grid.ColumnWidth = colSize;
        grid.CanUserAddRows = false;
        grid.AlternationCount = 2;
        BuildInto(grid);
        return grid;
    }
}

将它们放在一起,这是一个示例用途:

void SimpleTest_Loaded(object sender, RoutedEventArgs e)
    {            
        DataRow headers = new DataRow("Level", "Weapon Type", "vs None", "vs Leather", "vs Studded", "vs Brigandine");            
        GridConstructor gridConstructor = new GridConstructor(headers);            

        var weaponType = "Slash";
        for (int level = 1; level < 10; level++)
        {
            int damage = DiceCup.RollMulti(8, level);
            int damCloth = damage - DiceCup.RollMulti(2, level);
            int damLeather = damage - DiceCup.RollMulti(3, level);
            int damStudded = damage - DiceCup.RollMulti(4, level);
            int damBrigandine = damage - DiceCup.RollMulti(5, level);

            DataRow row = new DataRow(level, weaponType, damage, damCloth, damLeather, damStudded, damBrigandine);
            gridConstructor.Rows.Add(row);                
        }

        //Create the grid.
        var grid = gridConstructor.Create(100);


        //Create a chart.
        Chart chart = new Chart();
        chart.Height = 200;
        chart.LegendTitle = "Legend";
        chart.Title = "Slash vs Armor Types";                       
        chart.DataContext = gridConstructor.Rows;            


        //Create our series, or lines.
        LineSeries slashVsNone = new LineSeries();
        slashVsNone.Title = "vs None";
        slashVsNone.DependentValueBinding = new Binding("[2]");
        slashVsNone.IndependentValueBinding = new Binding("[0]");
        slashVsNone.ItemsSource = gridConstructor.Rows;            
        chart.Series.Add(slashVsNone);

        //Presentation is a stackpanel on the page.            
        presentation.Children.Add(grid);
        presentation.Children.Add(chart);             
    }

输出:

alt text http://quiteabnormal.com/images/codeSample.jpg

请注意,网格着色来自页面上设置的通用样式。如果你使用GridConstructor.BuildInto()方法,你可以指定一个你自己在Blend中预先格式化的网格或者某些。

只有一件事,GridConstructor对列的初始设置做了一些假设。如果你愿意,你可以更改类以使其更具可定制性,但这是我需要的,所以我希望能够毫不费力地制作它。