tags:

views:

2460

answers:

3

I want to bind the columns of my WPF DataGrid to some objects in a Dictionary like this:

Binding Path=Objects[i]

where Objects is my Dictionary of objects, so that each cell will represent an Object element. How can I do that?

I suppose that I need to create a template for my cell, which I did, but how to get the result of column binding in my template? I know that by default the content of a DataGridCell is a TextBlock and it's Text property is set through column binding result, but if that result is an object I guess that I have to create a ContentTemplate. How do I do that, as the stuff I tried is not displaying anything.

Here it is what I tried:

<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>

So, to make myself completly clear, i want to get in CurrentObject property of my DataGridCellControl the current object that should result if I set the column binding in my data grid like this Path=Objects[i].

Thank you for any suggestion,

John.

A: 

Try this:

<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>

Where in ItemsSource="{Binding ElementName=window1, Path=Users, Mode=TwoWay}"

  • ElementName is the name of the Window in XAML (just add x:Name="window1" to the Window tag as with any other ontrol.

  • Users is a List, should work the same with Dictionary

  • Mode=TwoWay means that if the grid gets modified, the list will get modified too, and vice versa (Two way binding)

EDIT:

Try this:

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;
    }

And call this method under 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;
     }

I'm not saying it's the best solution, but it could help. Let me know.

Carlo
Thanks Carlo for your replay,Is though a similar way of doing that with WPF DataGrid?Regards,John
Oh, and something else, I create my columns dynamically, so I will need a global CellTemplate applicable to all cells. Any idea on how can I achive that?
Maybe you should just create the data table out of the dictionary and bind the datagrid to that datatable, think this would help you?
Carlo
I'm not sure how can I do that. My scenario is like following:My data source is ObservableColection<Object>.The Object looks like this:class Object{int Col1,Col2,Col3;Dictionary<int, OtherColumns> otherColumns;}Now the otherColumns is dynamicly set and can be updated at any time. I think the approach you initialy proposed with a ListView would have worked, I'm not to familiar with ListView but I think that can be styled and used like a DataGrid. I won't find any solution I would have to migrate to ListView.On a ListView can be defined a global CellTemplate?
I don't think there is, I've only used it under each GridViewColumn (GridViewColumn.CellTemplate) like in my example. Try the code I put in the edit, I'll investigate on this a little more.
Carlo
A: 
Vassi
A: 

I want to add image in datatable ... and also want to set the default image to cross. and tick to those users that are online... but how?

Aizaz