How to populate a WPF grid based on a 2-dimensional array











up vote
54
down vote

favorite
37












I have a 2-dimensional array of objects and I basically want to databind each one to a cell in a WPF grid. Currently I have this working but I am doing most of it procedurally. I create the correct number of row and column definitions, then I loop through the cells and create the controls and set up the correct bindings for each one.



At a minimum I would like to be able to use a template to specify the controls and bindings in xaml. Ideally I would like to get rid of the procedural code and just do it all with databinding, but I'm not sure that's possible.



Here is the code I am currently using:



public void BindGrid()
{
m_Grid.Children.Clear();
m_Grid.ColumnDefinitions.Clear();
m_Grid.RowDefinitions.Clear();

for (int x = 0; x < MefGrid.Width; x++)
{
m_Grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), });
}

for (int y = 0; y < MefGrid.Height; y++)
{
m_Grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), });
}

for (int x = 0; x < MefGrid.Width; x++)
{
for (int y = 0; y < MefGrid.Height; y++)
{
Cell cell = (Cell)MefGrid[x, y];

SolidColorBrush brush = new SolidColorBrush();

var binding = new Binding("On");
binding.Converter = new BoolColorConverter();
binding.Mode = BindingMode.OneWay;

BindingOperations.SetBinding(brush, SolidColorBrush.ColorProperty, binding);

var rect = new Rectangle();
rect.DataContext = cell;
rect.Fill = brush;
rect.SetValue(Grid.RowProperty, y);
rect.SetValue(Grid.ColumnProperty, x);
m_Grid.Children.Add(rect);
}
}

}









share|improve this question




























    up vote
    54
    down vote

    favorite
    37












    I have a 2-dimensional array of objects and I basically want to databind each one to a cell in a WPF grid. Currently I have this working but I am doing most of it procedurally. I create the correct number of row and column definitions, then I loop through the cells and create the controls and set up the correct bindings for each one.



    At a minimum I would like to be able to use a template to specify the controls and bindings in xaml. Ideally I would like to get rid of the procedural code and just do it all with databinding, but I'm not sure that's possible.



    Here is the code I am currently using:



    public void BindGrid()
    {
    m_Grid.Children.Clear();
    m_Grid.ColumnDefinitions.Clear();
    m_Grid.RowDefinitions.Clear();

    for (int x = 0; x < MefGrid.Width; x++)
    {
    m_Grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), });
    }

    for (int y = 0; y < MefGrid.Height; y++)
    {
    m_Grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), });
    }

    for (int x = 0; x < MefGrid.Width; x++)
    {
    for (int y = 0; y < MefGrid.Height; y++)
    {
    Cell cell = (Cell)MefGrid[x, y];

    SolidColorBrush brush = new SolidColorBrush();

    var binding = new Binding("On");
    binding.Converter = new BoolColorConverter();
    binding.Mode = BindingMode.OneWay;

    BindingOperations.SetBinding(brush, SolidColorBrush.ColorProperty, binding);

    var rect = new Rectangle();
    rect.DataContext = cell;
    rect.Fill = brush;
    rect.SetValue(Grid.RowProperty, y);
    rect.SetValue(Grid.ColumnProperty, x);
    m_Grid.Children.Add(rect);
    }
    }

    }









    share|improve this question


























      up vote
      54
      down vote

      favorite
      37









      up vote
      54
      down vote

      favorite
      37






      37





      I have a 2-dimensional array of objects and I basically want to databind each one to a cell in a WPF grid. Currently I have this working but I am doing most of it procedurally. I create the correct number of row and column definitions, then I loop through the cells and create the controls and set up the correct bindings for each one.



      At a minimum I would like to be able to use a template to specify the controls and bindings in xaml. Ideally I would like to get rid of the procedural code and just do it all with databinding, but I'm not sure that's possible.



      Here is the code I am currently using:



      public void BindGrid()
      {
      m_Grid.Children.Clear();
      m_Grid.ColumnDefinitions.Clear();
      m_Grid.RowDefinitions.Clear();

      for (int x = 0; x < MefGrid.Width; x++)
      {
      m_Grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), });
      }

      for (int y = 0; y < MefGrid.Height; y++)
      {
      m_Grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), });
      }

      for (int x = 0; x < MefGrid.Width; x++)
      {
      for (int y = 0; y < MefGrid.Height; y++)
      {
      Cell cell = (Cell)MefGrid[x, y];

      SolidColorBrush brush = new SolidColorBrush();

      var binding = new Binding("On");
      binding.Converter = new BoolColorConverter();
      binding.Mode = BindingMode.OneWay;

      BindingOperations.SetBinding(brush, SolidColorBrush.ColorProperty, binding);

      var rect = new Rectangle();
      rect.DataContext = cell;
      rect.Fill = brush;
      rect.SetValue(Grid.RowProperty, y);
      rect.SetValue(Grid.ColumnProperty, x);
      m_Grid.Children.Add(rect);
      }
      }

      }









      share|improve this question















      I have a 2-dimensional array of objects and I basically want to databind each one to a cell in a WPF grid. Currently I have this working but I am doing most of it procedurally. I create the correct number of row and column definitions, then I loop through the cells and create the controls and set up the correct bindings for each one.



      At a minimum I would like to be able to use a template to specify the controls and bindings in xaml. Ideally I would like to get rid of the procedural code and just do it all with databinding, but I'm not sure that's possible.



      Here is the code I am currently using:



      public void BindGrid()
      {
      m_Grid.Children.Clear();
      m_Grid.ColumnDefinitions.Clear();
      m_Grid.RowDefinitions.Clear();

      for (int x = 0; x < MefGrid.Width; x++)
      {
      m_Grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), });
      }

      for (int y = 0; y < MefGrid.Height; y++)
      {
      m_Grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), });
      }

      for (int x = 0; x < MefGrid.Width; x++)
      {
      for (int y = 0; y < MefGrid.Height; y++)
      {
      Cell cell = (Cell)MefGrid[x, y];

      SolidColorBrush brush = new SolidColorBrush();

      var binding = new Binding("On");
      binding.Converter = new BoolColorConverter();
      binding.Mode = BindingMode.OneWay;

      BindingOperations.SetBinding(brush, SolidColorBrush.ColorProperty, binding);

      var rect = new Rectangle();
      rect.DataContext = cell;
      rect.Fill = brush;
      rect.SetValue(Grid.RowProperty, y);
      rect.SetValue(Grid.ColumnProperty, x);
      m_Grid.Children.Add(rect);
      }
      }

      }






      .net wpf data-binding templates grid






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 '08 at 1:15

























      asked Nov 10 '08 at 1:05









      Daniel Plaisted

      14.9k43853




      14.9k43853
























          5 Answers
          5






          active

          oldest

          votes

















          up vote
          64
          down vote



          accepted










          The purpose of the Grid is not for real databinding, it is just a panel. I am listing down the easiest way to accomplish the visualization of a two dimensional list



          <Window.Resources>
          <DataTemplate x:Key="DataTemplate_Level2">
          <Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4"/>
          </DataTemplate>

          <DataTemplate x:Key="DataTemplate_Level1">
          <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
          <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
          <StackPanel Orientation="Horizontal"/>
          </ItemsPanelTemplate>
          </ItemsControl.ItemsPanel>
          </ItemsControl>
          </DataTemplate>

          </Window.Resources>
          <Grid>
          <ItemsControl x:Name="lst" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
          </Grid>


          And in the code behind set the ItemsSource of lst with a TwoDimentional data structure.



            public Window1()
          {
          List<List<int>> lsts = new List<List<int>>();

          for (int i = 0; i < 5; i++)
          {
          lsts.Add(new List<int>());

          for (int j = 0; j < 5; j++)
          {
          lsts[i].Add(i * 10 + j);
          }
          }

          InitializeComponent();

          lst.ItemsSource = lsts;
          }


          This gives you the following screen as output. You can edit the DataTemplate_Level2 to add more specific data of your object.



          alt text






          share|improve this answer



















          • 1




            I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
            – Daniel Plaisted
            Nov 10 '08 at 2:52






          • 3




            WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
            – Jobi Joy
            Nov 13 '08 at 4:57






          • 1




            Is it possible to use the new WPF DataGrid to achieve this?
            – Brian Low
            Jul 10 '10 at 22:03






          • 2




            Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
            – ford
            Oct 22 '11 at 0:08






          • 1




            Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
            – Kranach
            May 13 '14 at 17:02


















          up vote
          42
          down vote













          Here is a Control called DataGrid2D that can be populated based on a 2D or

          1D array (or anything that implements the IList interface). It subclasses DataGrid and adds a property called ItemsSource2D which is used for binding against 2D or 1D sources. Library can be downloaded here and source code can be downloaded here.



          To use it just add a reference to DataGrid2DLibrary.dll, add this namespace



          xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"


          and then create a DataGrid2D and bind it to your IList, 2D array or 1D array like this



          <dg2d:DataGrid2D Name="dataGrid2D"
          ItemsSource2D="{Binding Int2DList}"/>


          enter image description here





          OLD POST

          Here is an implementation that can bind a 2D array to the WPF datagrid.



          Say we have this 2D array



          private int[,] m_intArray = new int[5, 5];
          ...
          for (int i = 0; i < 5; i++)
          {
          for (int j = 0; j < 5; j++)
          {
          m_intArray[i,j] = (i * 10 + j);
          }
          }


          And then we want to bind this 2D array to the WPF DataGrid and the changes we make shall be reflected in the array. To do this I used Eric Lippert's Ref class from this thread.



          public class Ref<T>  
          {
          private readonly Func<T> getter;
          private readonly Action<T> setter;
          public Ref(Func<T> getter, Action<T> setter)
          {
          this.getter = getter;
          this.setter = setter;
          }
          public T Value { get { return getter(); } set { setter(value); } }
          }


          Then I made a static helper class with a method that could take a 2D array and return a DataView using the Ref class above.



          public static DataView GetBindable2DArray<T>(T[,] array)
          {
          DataTable dataTable = new DataTable();
          for (int i = 0; i < array.GetLength(1); i++)
          {
          dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
          }
          for (int i = 0; i < array.GetLength(0); i++)
          {
          DataRow dataRow = dataTable.NewRow();
          dataTable.Rows.Add(dataRow);
          }
          DataView dataView = new DataView(dataTable);
          for (int i = 0; i < array.GetLength(0); i++)
          {
          for (int j = 0; j < array.GetLength(1); j++)
          {
          int a = i;
          int b = j;
          Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
          dataView[i][j] = refT;
          }
          }
          return dataView;
          }


          This would almost be enough to bind to but the Path in the Binding will point to the Ref object instead of the Ref.Value which we need so we have to change this when the Columns get generated.



          <DataGrid Name="c_dataGrid"
          RowHeaderWidth="0"
          ColumnHeaderHeight="0"
          AutoGenerateColumns="True"
          AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>

          private void c_dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
          {
          DataGridTextColumn column = e.Column as DataGridTextColumn;
          Binding binding = column.Binding as Binding;
          binding.Path = new PropertyPath(binding.Path.Path + ".Value");
          }


          And after this we can use



          c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);


          And the output will look like this



          alt text



          Any changes made in the DataGrid will be reflected in the m_intArray.






          share|improve this answer























          • Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
            – Slauma
            Feb 14 '11 at 17:57










          • @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
            – Fredrik Hedblad
            Feb 14 '11 at 18:45










          • I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
            – Slauma
            Feb 14 '11 at 20:23










          • @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
            – Fredrik Hedblad
            Feb 16 '11 at 8:09










          • Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
            – Fred
            Feb 17 '11 at 21:52


















          up vote
          3
          down vote













          I wrote a small library of attached properties for the DataGrid.
          Here is the source



          Sample, where Data2D is int[,]:



          <DataGrid HeadersVisibility="None"
          dataGrid2D:Source2D.ItemsSource2D="{Binding Data2D}" />


          Renders:
          enter image description here






          share|improve this answer





















          • Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
            – rolls
            Nov 7 '16 at 5:00


















          up vote
          0
          down vote













          You may want to check out this link: http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python



          If you use a List within a List you can use myList[x][y] to access a cell.






          share|improve this answer





















          • with a list inside a list it is usually mylist[y][x]
            – MikeT
            Jan 16 '13 at 9:31


















          up vote
          0
          down vote













          Here is another solution based on Meleak's answer but without requiring for an AutoGeneratingColumn event handler in the code behind of each binded DataGrid:



          public static DataView GetBindable2DArray<T>(T[,] array)
          {
          var table = new DataTable();
          for (var i = 0; i < array.GetLength(1); i++)
          {
          table.Columns.Add(i+1, typeof(bool))
          .ExtendedProperties.Add("idx", i); // Save original column index
          }
          for (var i = 0; i < array.GetLength(0); i++)
          {
          table.Rows.Add(table.NewRow());
          }

          var view = new DataView(table);
          for (var ri = 0; ri < array.GetLength(0); ri++)
          {
          for (var ci = 0; ci < array.GetLength(1); ci++)
          {
          view[ri][ci] = array[ri, ci];
          }
          }

          // Avoids writing an 'AutogeneratingColumn' handler
          table.ColumnChanged += (s, e) =>
          {
          var ci = (int)e.Column.ExtendedProperties["idx"]; // Retrieve original column index
          var ri = e.Row.Table.Rows.IndexOf(e.Row); // Retrieve row index

          array[ri, ci] = (T)view[ri][ci];
          };

          return view;
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f276808%2fhow-to-populate-a-wpf-grid-based-on-a-2-dimensional-array%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            5 Answers
            5






            active

            oldest

            votes








            5 Answers
            5






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            64
            down vote



            accepted










            The purpose of the Grid is not for real databinding, it is just a panel. I am listing down the easiest way to accomplish the visualization of a two dimensional list



            <Window.Resources>
            <DataTemplate x:Key="DataTemplate_Level2">
            <Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4"/>
            </DataTemplate>

            <DataTemplate x:Key="DataTemplate_Level1">
            <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
            <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            </ItemsControl>
            </DataTemplate>

            </Window.Resources>
            <Grid>
            <ItemsControl x:Name="lst" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
            </Grid>


            And in the code behind set the ItemsSource of lst with a TwoDimentional data structure.



              public Window1()
            {
            List<List<int>> lsts = new List<List<int>>();

            for (int i = 0; i < 5; i++)
            {
            lsts.Add(new List<int>());

            for (int j = 0; j < 5; j++)
            {
            lsts[i].Add(i * 10 + j);
            }
            }

            InitializeComponent();

            lst.ItemsSource = lsts;
            }


            This gives you the following screen as output. You can edit the DataTemplate_Level2 to add more specific data of your object.



            alt text






            share|improve this answer



















            • 1




              I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
              – Daniel Plaisted
              Nov 10 '08 at 2:52






            • 3




              WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
              – Jobi Joy
              Nov 13 '08 at 4:57






            • 1




              Is it possible to use the new WPF DataGrid to achieve this?
              – Brian Low
              Jul 10 '10 at 22:03






            • 2




              Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
              – ford
              Oct 22 '11 at 0:08






            • 1




              Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
              – Kranach
              May 13 '14 at 17:02















            up vote
            64
            down vote



            accepted










            The purpose of the Grid is not for real databinding, it is just a panel. I am listing down the easiest way to accomplish the visualization of a two dimensional list



            <Window.Resources>
            <DataTemplate x:Key="DataTemplate_Level2">
            <Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4"/>
            </DataTemplate>

            <DataTemplate x:Key="DataTemplate_Level1">
            <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
            <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            </ItemsControl>
            </DataTemplate>

            </Window.Resources>
            <Grid>
            <ItemsControl x:Name="lst" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
            </Grid>


            And in the code behind set the ItemsSource of lst with a TwoDimentional data structure.



              public Window1()
            {
            List<List<int>> lsts = new List<List<int>>();

            for (int i = 0; i < 5; i++)
            {
            lsts.Add(new List<int>());

            for (int j = 0; j < 5; j++)
            {
            lsts[i].Add(i * 10 + j);
            }
            }

            InitializeComponent();

            lst.ItemsSource = lsts;
            }


            This gives you the following screen as output. You can edit the DataTemplate_Level2 to add more specific data of your object.



            alt text






            share|improve this answer



















            • 1




              I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
              – Daniel Plaisted
              Nov 10 '08 at 2:52






            • 3




              WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
              – Jobi Joy
              Nov 13 '08 at 4:57






            • 1




              Is it possible to use the new WPF DataGrid to achieve this?
              – Brian Low
              Jul 10 '10 at 22:03






            • 2




              Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
              – ford
              Oct 22 '11 at 0:08






            • 1




              Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
              – Kranach
              May 13 '14 at 17:02













            up vote
            64
            down vote



            accepted







            up vote
            64
            down vote



            accepted






            The purpose of the Grid is not for real databinding, it is just a panel. I am listing down the easiest way to accomplish the visualization of a two dimensional list



            <Window.Resources>
            <DataTemplate x:Key="DataTemplate_Level2">
            <Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4"/>
            </DataTemplate>

            <DataTemplate x:Key="DataTemplate_Level1">
            <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
            <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            </ItemsControl>
            </DataTemplate>

            </Window.Resources>
            <Grid>
            <ItemsControl x:Name="lst" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
            </Grid>


            And in the code behind set the ItemsSource of lst with a TwoDimentional data structure.



              public Window1()
            {
            List<List<int>> lsts = new List<List<int>>();

            for (int i = 0; i < 5; i++)
            {
            lsts.Add(new List<int>());

            for (int j = 0; j < 5; j++)
            {
            lsts[i].Add(i * 10 + j);
            }
            }

            InitializeComponent();

            lst.ItemsSource = lsts;
            }


            This gives you the following screen as output. You can edit the DataTemplate_Level2 to add more specific data of your object.



            alt text






            share|improve this answer














            The purpose of the Grid is not for real databinding, it is just a panel. I am listing down the easiest way to accomplish the visualization of a two dimensional list



            <Window.Resources>
            <DataTemplate x:Key="DataTemplate_Level2">
            <Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4"/>
            </DataTemplate>

            <DataTemplate x:Key="DataTemplate_Level1">
            <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
            <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            </ItemsControl>
            </DataTemplate>

            </Window.Resources>
            <Grid>
            <ItemsControl x:Name="lst" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
            </Grid>


            And in the code behind set the ItemsSource of lst with a TwoDimentional data structure.



              public Window1()
            {
            List<List<int>> lsts = new List<List<int>>();

            for (int i = 0; i < 5; i++)
            {
            lsts.Add(new List<int>());

            for (int j = 0; j < 5; j++)
            {
            lsts[i].Add(i * 10 + j);
            }
            }

            InitializeComponent();

            lst.ItemsSource = lsts;
            }


            This gives you the following screen as output. You can edit the DataTemplate_Level2 to add more specific data of your object.



            alt text







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jul 27 '15 at 10:41









            Ilmari Karonen

            36.9k566124




            36.9k566124










            answered Nov 10 '08 at 1:50









            Jobi Joy

            31.7k1998116




            31.7k1998116








            • 1




              I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
              – Daniel Plaisted
              Nov 10 '08 at 2:52






            • 3




              WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
              – Jobi Joy
              Nov 13 '08 at 4:57






            • 1




              Is it possible to use the new WPF DataGrid to achieve this?
              – Brian Low
              Jul 10 '10 at 22:03






            • 2




              Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
              – ford
              Oct 22 '11 at 0:08






            • 1




              Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
              – Kranach
              May 13 '14 at 17:02














            • 1




              I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
              – Daniel Plaisted
              Nov 10 '08 at 2:52






            • 3




              WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
              – Jobi Joy
              Nov 13 '08 at 4:57






            • 1




              Is it possible to use the new WPF DataGrid to achieve this?
              – Brian Low
              Jul 10 '10 at 22:03






            • 2




              Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
              – ford
              Oct 22 '11 at 0:08






            • 1




              Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
              – Kranach
              May 13 '14 at 17:02








            1




            1




            I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
            – Daniel Plaisted
            Nov 10 '08 at 2:52




            I don't necessarily need to use a grid for the databinding, but I don't want to have to create a list of lists for the source. I want to use an object that has an indexer that takes two parameters, x and y.
            – Daniel Plaisted
            Nov 10 '08 at 2:52




            3




            3




            WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
            – Jobi Joy
            Nov 13 '08 at 4:57




            WPF binding cant recongnize an array, it has to be an Enumerable collection. So better create a List of List and databind it.
            – Jobi Joy
            Nov 13 '08 at 4:57




            1




            1




            Is it possible to use the new WPF DataGrid to achieve this?
            – Brian Low
            Jul 10 '10 at 22:03




            Is it possible to use the new WPF DataGrid to achieve this?
            – Brian Low
            Jul 10 '10 at 22:03




            2




            2




            Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
            – ford
            Oct 22 '11 at 0:08




            Bonus points for using a reference image to display correct results. A picture is worth 2^10 words.
            – ford
            Oct 22 '11 at 0:08




            1




            1




            Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
            – Kranach
            May 13 '14 at 17:02




            Quick question, do you really need to use DynamicResource in this example, or could Static do as well?
            – Kranach
            May 13 '14 at 17:02












            up vote
            42
            down vote













            Here is a Control called DataGrid2D that can be populated based on a 2D or

            1D array (or anything that implements the IList interface). It subclasses DataGrid and adds a property called ItemsSource2D which is used for binding against 2D or 1D sources. Library can be downloaded here and source code can be downloaded here.



            To use it just add a reference to DataGrid2DLibrary.dll, add this namespace



            xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"


            and then create a DataGrid2D and bind it to your IList, 2D array or 1D array like this



            <dg2d:DataGrid2D Name="dataGrid2D"
            ItemsSource2D="{Binding Int2DList}"/>


            enter image description here





            OLD POST

            Here is an implementation that can bind a 2D array to the WPF datagrid.



            Say we have this 2D array



            private int[,] m_intArray = new int[5, 5];
            ...
            for (int i = 0; i < 5; i++)
            {
            for (int j = 0; j < 5; j++)
            {
            m_intArray[i,j] = (i * 10 + j);
            }
            }


            And then we want to bind this 2D array to the WPF DataGrid and the changes we make shall be reflected in the array. To do this I used Eric Lippert's Ref class from this thread.



            public class Ref<T>  
            {
            private readonly Func<T> getter;
            private readonly Action<T> setter;
            public Ref(Func<T> getter, Action<T> setter)
            {
            this.getter = getter;
            this.setter = setter;
            }
            public T Value { get { return getter(); } set { setter(value); } }
            }


            Then I made a static helper class with a method that could take a 2D array and return a DataView using the Ref class above.



            public static DataView GetBindable2DArray<T>(T[,] array)
            {
            DataTable dataTable = new DataTable();
            for (int i = 0; i < array.GetLength(1); i++)
            {
            dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
            }
            for (int i = 0; i < array.GetLength(0); i++)
            {
            DataRow dataRow = dataTable.NewRow();
            dataTable.Rows.Add(dataRow);
            }
            DataView dataView = new DataView(dataTable);
            for (int i = 0; i < array.GetLength(0); i++)
            {
            for (int j = 0; j < array.GetLength(1); j++)
            {
            int a = i;
            int b = j;
            Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
            dataView[i][j] = refT;
            }
            }
            return dataView;
            }


            This would almost be enough to bind to but the Path in the Binding will point to the Ref object instead of the Ref.Value which we need so we have to change this when the Columns get generated.



            <DataGrid Name="c_dataGrid"
            RowHeaderWidth="0"
            ColumnHeaderHeight="0"
            AutoGenerateColumns="True"
            AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>

            private void c_dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
            DataGridTextColumn column = e.Column as DataGridTextColumn;
            Binding binding = column.Binding as Binding;
            binding.Path = new PropertyPath(binding.Path.Path + ".Value");
            }


            And after this we can use



            c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);


            And the output will look like this



            alt text



            Any changes made in the DataGrid will be reflected in the m_intArray.






            share|improve this answer























            • Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
              – Slauma
              Feb 14 '11 at 17:57










            • @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
              – Fredrik Hedblad
              Feb 14 '11 at 18:45










            • I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
              – Slauma
              Feb 14 '11 at 20:23










            • @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
              – Fredrik Hedblad
              Feb 16 '11 at 8:09










            • Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
              – Fred
              Feb 17 '11 at 21:52















            up vote
            42
            down vote













            Here is a Control called DataGrid2D that can be populated based on a 2D or

            1D array (or anything that implements the IList interface). It subclasses DataGrid and adds a property called ItemsSource2D which is used for binding against 2D or 1D sources. Library can be downloaded here and source code can be downloaded here.



            To use it just add a reference to DataGrid2DLibrary.dll, add this namespace



            xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"


            and then create a DataGrid2D and bind it to your IList, 2D array or 1D array like this



            <dg2d:DataGrid2D Name="dataGrid2D"
            ItemsSource2D="{Binding Int2DList}"/>


            enter image description here





            OLD POST

            Here is an implementation that can bind a 2D array to the WPF datagrid.



            Say we have this 2D array



            private int[,] m_intArray = new int[5, 5];
            ...
            for (int i = 0; i < 5; i++)
            {
            for (int j = 0; j < 5; j++)
            {
            m_intArray[i,j] = (i * 10 + j);
            }
            }


            And then we want to bind this 2D array to the WPF DataGrid and the changes we make shall be reflected in the array. To do this I used Eric Lippert's Ref class from this thread.



            public class Ref<T>  
            {
            private readonly Func<T> getter;
            private readonly Action<T> setter;
            public Ref(Func<T> getter, Action<T> setter)
            {
            this.getter = getter;
            this.setter = setter;
            }
            public T Value { get { return getter(); } set { setter(value); } }
            }


            Then I made a static helper class with a method that could take a 2D array and return a DataView using the Ref class above.



            public static DataView GetBindable2DArray<T>(T[,] array)
            {
            DataTable dataTable = new DataTable();
            for (int i = 0; i < array.GetLength(1); i++)
            {
            dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
            }
            for (int i = 0; i < array.GetLength(0); i++)
            {
            DataRow dataRow = dataTable.NewRow();
            dataTable.Rows.Add(dataRow);
            }
            DataView dataView = new DataView(dataTable);
            for (int i = 0; i < array.GetLength(0); i++)
            {
            for (int j = 0; j < array.GetLength(1); j++)
            {
            int a = i;
            int b = j;
            Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
            dataView[i][j] = refT;
            }
            }
            return dataView;
            }


            This would almost be enough to bind to but the Path in the Binding will point to the Ref object instead of the Ref.Value which we need so we have to change this when the Columns get generated.



            <DataGrid Name="c_dataGrid"
            RowHeaderWidth="0"
            ColumnHeaderHeight="0"
            AutoGenerateColumns="True"
            AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>

            private void c_dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
            DataGridTextColumn column = e.Column as DataGridTextColumn;
            Binding binding = column.Binding as Binding;
            binding.Path = new PropertyPath(binding.Path.Path + ".Value");
            }


            And after this we can use



            c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);


            And the output will look like this



            alt text



            Any changes made in the DataGrid will be reflected in the m_intArray.






            share|improve this answer























            • Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
              – Slauma
              Feb 14 '11 at 17:57










            • @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
              – Fredrik Hedblad
              Feb 14 '11 at 18:45










            • I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
              – Slauma
              Feb 14 '11 at 20:23










            • @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
              – Fredrik Hedblad
              Feb 16 '11 at 8:09










            • Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
              – Fred
              Feb 17 '11 at 21:52













            up vote
            42
            down vote










            up vote
            42
            down vote









            Here is a Control called DataGrid2D that can be populated based on a 2D or

            1D array (or anything that implements the IList interface). It subclasses DataGrid and adds a property called ItemsSource2D which is used for binding against 2D or 1D sources. Library can be downloaded here and source code can be downloaded here.



            To use it just add a reference to DataGrid2DLibrary.dll, add this namespace



            xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"


            and then create a DataGrid2D and bind it to your IList, 2D array or 1D array like this



            <dg2d:DataGrid2D Name="dataGrid2D"
            ItemsSource2D="{Binding Int2DList}"/>


            enter image description here





            OLD POST

            Here is an implementation that can bind a 2D array to the WPF datagrid.



            Say we have this 2D array



            private int[,] m_intArray = new int[5, 5];
            ...
            for (int i = 0; i < 5; i++)
            {
            for (int j = 0; j < 5; j++)
            {
            m_intArray[i,j] = (i * 10 + j);
            }
            }


            And then we want to bind this 2D array to the WPF DataGrid and the changes we make shall be reflected in the array. To do this I used Eric Lippert's Ref class from this thread.



            public class Ref<T>  
            {
            private readonly Func<T> getter;
            private readonly Action<T> setter;
            public Ref(Func<T> getter, Action<T> setter)
            {
            this.getter = getter;
            this.setter = setter;
            }
            public T Value { get { return getter(); } set { setter(value); } }
            }


            Then I made a static helper class with a method that could take a 2D array and return a DataView using the Ref class above.



            public static DataView GetBindable2DArray<T>(T[,] array)
            {
            DataTable dataTable = new DataTable();
            for (int i = 0; i < array.GetLength(1); i++)
            {
            dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
            }
            for (int i = 0; i < array.GetLength(0); i++)
            {
            DataRow dataRow = dataTable.NewRow();
            dataTable.Rows.Add(dataRow);
            }
            DataView dataView = new DataView(dataTable);
            for (int i = 0; i < array.GetLength(0); i++)
            {
            for (int j = 0; j < array.GetLength(1); j++)
            {
            int a = i;
            int b = j;
            Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
            dataView[i][j] = refT;
            }
            }
            return dataView;
            }


            This would almost be enough to bind to but the Path in the Binding will point to the Ref object instead of the Ref.Value which we need so we have to change this when the Columns get generated.



            <DataGrid Name="c_dataGrid"
            RowHeaderWidth="0"
            ColumnHeaderHeight="0"
            AutoGenerateColumns="True"
            AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>

            private void c_dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
            DataGridTextColumn column = e.Column as DataGridTextColumn;
            Binding binding = column.Binding as Binding;
            binding.Path = new PropertyPath(binding.Path.Path + ".Value");
            }


            And after this we can use



            c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);


            And the output will look like this



            alt text



            Any changes made in the DataGrid will be reflected in the m_intArray.






            share|improve this answer














            Here is a Control called DataGrid2D that can be populated based on a 2D or

            1D array (or anything that implements the IList interface). It subclasses DataGrid and adds a property called ItemsSource2D which is used for binding against 2D or 1D sources. Library can be downloaded here and source code can be downloaded here.



            To use it just add a reference to DataGrid2DLibrary.dll, add this namespace



            xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"


            and then create a DataGrid2D and bind it to your IList, 2D array or 1D array like this



            <dg2d:DataGrid2D Name="dataGrid2D"
            ItemsSource2D="{Binding Int2DList}"/>


            enter image description here





            OLD POST

            Here is an implementation that can bind a 2D array to the WPF datagrid.



            Say we have this 2D array



            private int[,] m_intArray = new int[5, 5];
            ...
            for (int i = 0; i < 5; i++)
            {
            for (int j = 0; j < 5; j++)
            {
            m_intArray[i,j] = (i * 10 + j);
            }
            }


            And then we want to bind this 2D array to the WPF DataGrid and the changes we make shall be reflected in the array. To do this I used Eric Lippert's Ref class from this thread.



            public class Ref<T>  
            {
            private readonly Func<T> getter;
            private readonly Action<T> setter;
            public Ref(Func<T> getter, Action<T> setter)
            {
            this.getter = getter;
            this.setter = setter;
            }
            public T Value { get { return getter(); } set { setter(value); } }
            }


            Then I made a static helper class with a method that could take a 2D array and return a DataView using the Ref class above.



            public static DataView GetBindable2DArray<T>(T[,] array)
            {
            DataTable dataTable = new DataTable();
            for (int i = 0; i < array.GetLength(1); i++)
            {
            dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
            }
            for (int i = 0; i < array.GetLength(0); i++)
            {
            DataRow dataRow = dataTable.NewRow();
            dataTable.Rows.Add(dataRow);
            }
            DataView dataView = new DataView(dataTable);
            for (int i = 0; i < array.GetLength(0); i++)
            {
            for (int j = 0; j < array.GetLength(1); j++)
            {
            int a = i;
            int b = j;
            Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
            dataView[i][j] = refT;
            }
            }
            return dataView;
            }


            This would almost be enough to bind to but the Path in the Binding will point to the Ref object instead of the Ref.Value which we need so we have to change this when the Columns get generated.



            <DataGrid Name="c_dataGrid"
            RowHeaderWidth="0"
            ColumnHeaderHeight="0"
            AutoGenerateColumns="True"
            AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>

            private void c_dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
            DataGridTextColumn column = e.Column as DataGridTextColumn;
            Binding binding = column.Binding as Binding;
            binding.Path = new PropertyPath(binding.Path.Path + ".Value");
            }


            And after this we can use



            c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);


            And the output will look like this



            alt text



            Any changes made in the DataGrid will be reflected in the m_intArray.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 23 '17 at 11:33









            Community

            11




            11










            answered Oct 23 '10 at 4:02









            Fredrik Hedblad

            69.9k18215252




            69.9k18215252












            • Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
              – Slauma
              Feb 14 '11 at 17:57










            • @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
              – Fredrik Hedblad
              Feb 14 '11 at 18:45










            • I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
              – Slauma
              Feb 14 '11 at 20:23










            • @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
              – Fredrik Hedblad
              Feb 16 '11 at 8:09










            • Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
              – Fred
              Feb 17 '11 at 21:52


















            • Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
              – Slauma
              Feb 14 '11 at 17:57










            • @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
              – Fredrik Hedblad
              Feb 14 '11 at 18:45










            • I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
              – Slauma
              Feb 14 '11 at 20:23










            • @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
              – Fredrik Hedblad
              Feb 16 '11 at 8:09










            • Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
              – Fred
              Feb 17 '11 at 21:52
















            Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
            – Slauma
            Feb 14 '11 at 17:57




            Great example, thanks for sharing it! You had a question in DataGrid2D.cs: "Better way to find this out?". I think, you can write: bool multiDimensionalArray = type.IsArray && type.GetArrayRank() == 2; and the if statement two lines above: if (e.NewValue is IList && (!type.IsArray || type.GetArrayRank() <= 2)) That seems to work, couldn't find an issue during quick test of the examples.
            – Slauma
            Feb 14 '11 at 17:57












            @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
            – Fredrik Hedblad
            Feb 14 '11 at 18:45




            @Slauma: Glad you liked it and thanks for the feedback! I was hoping somebody would eventually give me an update on that :) I'll try it out and update the lib! Thanks again!
            – Fredrik Hedblad
            Feb 14 '11 at 18:45












            I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
            – Slauma
            Feb 14 '11 at 20:23




            I'm just testing and playing around a bit ;) There seems to be another minor glitch: I think, in the ItemsSource2DPropertyChanged EventHandler you need to consider the case that e.NewValue is null. When someone sets the ItemsSource2D to null it crashes. I just had this situation accidentally. I've simply placed a if (e.NewValue != null) around the whole EventHandler. It doesn't crash anymore, but I'm not sure if that's sufficient. Perhaps also dataGrid2D.ItemsSource must be set to null??
            – Slauma
            Feb 14 '11 at 20:23












            @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
            – Fredrik Hedblad
            Feb 16 '11 at 8:09




            @Slauma: It definitely shouldn't crash when setting ItemsSource2D to null :) That was previously handled by the if statement but due to an optimization attempt I accidently broke it.. I uploaded a new version that implements the suggestion from your first comment and fix the null bug. Thanks again!
            – Fredrik Hedblad
            Feb 16 '11 at 8:09












            Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
            – Fred
            Feb 17 '11 at 21:52




            Hi Meleak, would it be possible to get the source of your lib DataGrid2D? Thx Fred
            – Fred
            Feb 17 '11 at 21:52










            up vote
            3
            down vote













            I wrote a small library of attached properties for the DataGrid.
            Here is the source



            Sample, where Data2D is int[,]:



            <DataGrid HeadersVisibility="None"
            dataGrid2D:Source2D.ItemsSource2D="{Binding Data2D}" />


            Renders:
            enter image description here






            share|improve this answer





















            • Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
              – rolls
              Nov 7 '16 at 5:00















            up vote
            3
            down vote













            I wrote a small library of attached properties for the DataGrid.
            Here is the source



            Sample, where Data2D is int[,]:



            <DataGrid HeadersVisibility="None"
            dataGrid2D:Source2D.ItemsSource2D="{Binding Data2D}" />


            Renders:
            enter image description here






            share|improve this answer





















            • Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
              – rolls
              Nov 7 '16 at 5:00













            up vote
            3
            down vote










            up vote
            3
            down vote









            I wrote a small library of attached properties for the DataGrid.
            Here is the source



            Sample, where Data2D is int[,]:



            <DataGrid HeadersVisibility="None"
            dataGrid2D:Source2D.ItemsSource2D="{Binding Data2D}" />


            Renders:
            enter image description here






            share|improve this answer












            I wrote a small library of attached properties for the DataGrid.
            Here is the source



            Sample, where Data2D is int[,]:



            <DataGrid HeadersVisibility="None"
            dataGrid2D:Source2D.ItemsSource2D="{Binding Data2D}" />


            Renders:
            enter image description here







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jun 28 '15 at 18:08









            Johan Larsson

            10.8k84768




            10.8k84768












            • Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
              – rolls
              Nov 7 '16 at 5:00


















            • Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
              – rolls
              Nov 7 '16 at 5:00
















            Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
            – rolls
            Nov 7 '16 at 5:00




            Surprised there is no comments to this. Nothing else I can find for doing something simple like this. Spend days trying to bind a 2D array to a gridview! So difficult when it takes less than 10 minutes in winforms
            – rolls
            Nov 7 '16 at 5:00










            up vote
            0
            down vote













            You may want to check out this link: http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python



            If you use a List within a List you can use myList[x][y] to access a cell.






            share|improve this answer





















            • with a list inside a list it is usually mylist[y][x]
              – MikeT
              Jan 16 '13 at 9:31















            up vote
            0
            down vote













            You may want to check out this link: http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python



            If you use a List within a List you can use myList[x][y] to access a cell.






            share|improve this answer





















            • with a list inside a list it is usually mylist[y][x]
              – MikeT
              Jan 16 '13 at 9:31













            up vote
            0
            down vote










            up vote
            0
            down vote









            You may want to check out this link: http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python



            If you use a List within a List you can use myList[x][y] to access a cell.






            share|improve this answer












            You may want to check out this link: http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python



            If you use a List within a List you can use myList[x][y] to access a cell.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Oct 28 '09 at 9:19









            Torsten

            7141134




            7141134












            • with a list inside a list it is usually mylist[y][x]
              – MikeT
              Jan 16 '13 at 9:31


















            • with a list inside a list it is usually mylist[y][x]
              – MikeT
              Jan 16 '13 at 9:31
















            with a list inside a list it is usually mylist[y][x]
            – MikeT
            Jan 16 '13 at 9:31




            with a list inside a list it is usually mylist[y][x]
            – MikeT
            Jan 16 '13 at 9:31










            up vote
            0
            down vote













            Here is another solution based on Meleak's answer but without requiring for an AutoGeneratingColumn event handler in the code behind of each binded DataGrid:



            public static DataView GetBindable2DArray<T>(T[,] array)
            {
            var table = new DataTable();
            for (var i = 0; i < array.GetLength(1); i++)
            {
            table.Columns.Add(i+1, typeof(bool))
            .ExtendedProperties.Add("idx", i); // Save original column index
            }
            for (var i = 0; i < array.GetLength(0); i++)
            {
            table.Rows.Add(table.NewRow());
            }

            var view = new DataView(table);
            for (var ri = 0; ri < array.GetLength(0); ri++)
            {
            for (var ci = 0; ci < array.GetLength(1); ci++)
            {
            view[ri][ci] = array[ri, ci];
            }
            }

            // Avoids writing an 'AutogeneratingColumn' handler
            table.ColumnChanged += (s, e) =>
            {
            var ci = (int)e.Column.ExtendedProperties["idx"]; // Retrieve original column index
            var ri = e.Row.Table.Rows.IndexOf(e.Row); // Retrieve row index

            array[ri, ci] = (T)view[ri][ci];
            };

            return view;
            }





            share|improve this answer



























              up vote
              0
              down vote













              Here is another solution based on Meleak's answer but without requiring for an AutoGeneratingColumn event handler in the code behind of each binded DataGrid:



              public static DataView GetBindable2DArray<T>(T[,] array)
              {
              var table = new DataTable();
              for (var i = 0; i < array.GetLength(1); i++)
              {
              table.Columns.Add(i+1, typeof(bool))
              .ExtendedProperties.Add("idx", i); // Save original column index
              }
              for (var i = 0; i < array.GetLength(0); i++)
              {
              table.Rows.Add(table.NewRow());
              }

              var view = new DataView(table);
              for (var ri = 0; ri < array.GetLength(0); ri++)
              {
              for (var ci = 0; ci < array.GetLength(1); ci++)
              {
              view[ri][ci] = array[ri, ci];
              }
              }

              // Avoids writing an 'AutogeneratingColumn' handler
              table.ColumnChanged += (s, e) =>
              {
              var ci = (int)e.Column.ExtendedProperties["idx"]; // Retrieve original column index
              var ri = e.Row.Table.Rows.IndexOf(e.Row); // Retrieve row index

              array[ri, ci] = (T)view[ri][ci];
              };

              return view;
              }





              share|improve this answer

























                up vote
                0
                down vote










                up vote
                0
                down vote









                Here is another solution based on Meleak's answer but without requiring for an AutoGeneratingColumn event handler in the code behind of each binded DataGrid:



                public static DataView GetBindable2DArray<T>(T[,] array)
                {
                var table = new DataTable();
                for (var i = 0; i < array.GetLength(1); i++)
                {
                table.Columns.Add(i+1, typeof(bool))
                .ExtendedProperties.Add("idx", i); // Save original column index
                }
                for (var i = 0; i < array.GetLength(0); i++)
                {
                table.Rows.Add(table.NewRow());
                }

                var view = new DataView(table);
                for (var ri = 0; ri < array.GetLength(0); ri++)
                {
                for (var ci = 0; ci < array.GetLength(1); ci++)
                {
                view[ri][ci] = array[ri, ci];
                }
                }

                // Avoids writing an 'AutogeneratingColumn' handler
                table.ColumnChanged += (s, e) =>
                {
                var ci = (int)e.Column.ExtendedProperties["idx"]; // Retrieve original column index
                var ri = e.Row.Table.Rows.IndexOf(e.Row); // Retrieve row index

                array[ri, ci] = (T)view[ri][ci];
                };

                return view;
                }





                share|improve this answer














                Here is another solution based on Meleak's answer but without requiring for an AutoGeneratingColumn event handler in the code behind of each binded DataGrid:



                public static DataView GetBindable2DArray<T>(T[,] array)
                {
                var table = new DataTable();
                for (var i = 0; i < array.GetLength(1); i++)
                {
                table.Columns.Add(i+1, typeof(bool))
                .ExtendedProperties.Add("idx", i); // Save original column index
                }
                for (var i = 0; i < array.GetLength(0); i++)
                {
                table.Rows.Add(table.NewRow());
                }

                var view = new DataView(table);
                for (var ri = 0; ri < array.GetLength(0); ri++)
                {
                for (var ci = 0; ci < array.GetLength(1); ci++)
                {
                view[ri][ci] = array[ri, ci];
                }
                }

                // Avoids writing an 'AutogeneratingColumn' handler
                table.ColumnChanged += (s, e) =>
                {
                var ci = (int)e.Column.ExtendedProperties["idx"]; // Retrieve original column index
                var ri = e.Row.Table.Rows.IndexOf(e.Row); // Retrieve row index

                array[ri, ci] = (T)view[ri][ci];
                };

                return view;
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited May 23 '17 at 12:10









                Community

                11




                11










                answered Nov 30 '11 at 13:43









                CitizenInsane

                3,3461534




                3,3461534






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f276808%2fhow-to-populate-a-wpf-grid-based-on-a-2-dimensional-array%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    404 Error Contact Form 7 ajax form submitting

                    How to know if a Active Directory user can login interactively

                    Refactoring coordinates for Minecraft Pi buildings written in Python