MBZ
MBZ

Reputation: 27582

easily accessible array of controls

I'm quite new to whole XAML thing.

I need to create a table (grid) with constant number of rows and columns (e.g 2x5) and put a TextBlock in each cell.

How can I do this properly, so I can change the data of cells easily?

for example, I want to create a function which accepts 1 integer as offset:

void fillDate(int offset)

and fills the cells starting from offset incrementally.

i.e. calling the function with `fillData(3)' for a 2x5 would generate the following table:

 | | |1|2
3|4|5|6|7 

Upvotes: 1

Views: 137

Answers (2)

Yurii Zhukow
Yurii Zhukow

Reputation: 375

Try look to this. Here you use ListBox as container for your items array and UniformGrid as placeholder (you can bind number of rows and columns to properties of your class to alter them at run-time)

<Window x:Class=MyWindowClass ... >
    ... 
<ListBox 
 ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=MyWindowClass}, Path=myItems}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding Path=ColumnsInArray}"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=MyField}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

</Window>

and in code you just need to alter elements of your collection

class MyWindowClass: INotifyPropertyChanged
{
    public MyWindowClass():base()
    {
         ...
         InitializeComponent();
         myItems = new ObservableCollection<MyObject>();
         myItems.Add(new MyObject);// First Element
         myItems.Add(new MyObject);// Second Element
         ...
         myItems.Add(new MyObject);// Last Element
         ...
    }

    int columns=5;
    public int ColumnsInArray
    {
        get{return columns;} 
        set {columns=value; NotifyPropertyChanged("ColumnsInArray");}
    }

    public ObservableCollection<MyObject> myItems
    {
        get{ ... }
        set{ ... }
    }

setItem

    void setItem(int index,MyObject newObject)
    {
        ...
        myItems[index]=newObject;
        ...
    }

    void setItem(int x, int y, MyObject newObject)
    {
        ...
        int index = y*columns+x;
        setItem(index,newObject);
        ...
    }

INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;
    void NotifyPropertyChanged( string prop )
    {
        if( PropertyChanged != null ) 
        PropertyChanged( this , new PropertyChangedEventArgs( prop ) );
    }

}

public class MyObject
{
    public string MyField{get;set;}
}

Upvotes: 2

Chris Sinclair
Chris Sinclair

Reputation: 23198

It's nothing special, and coming from a Silverlight/XAML background, but will probably more or less work. You might need to tweak for slight API differences (writing in notepad without VS handy) and untested, but should give you what you need to get started.

private void fillDate(int offset)
{
    int rows = 2;
    int columns = 5;
    int currentEntry = 1;

    for(int rowIndex = 0; rowIndex < rows; rowIndex++)
    {
        for (int columnIndex = 0; columnIndex < columns; columnIndex++)
        {
            if (currentEntry > offset)
            {
                TextBlock textEntry = new TextBlock();
                textEntry.Text = currentEntry.ToString();
                Grid.SetRow(textEntry, rowIndex);
                Grid.SetColumn(textEntry, columnIndex);
            }
            currentEntry++;
        }
    }
}

EDIT: Just realized that you might be wanting a TextBlock with no text in the "empty" cells, in which case substitute the inner loop's code with:

TextBlock textEntry = new TextBlock();
Grid.SetRow(textEntry, rowIndex);
Grid.SetColumn(textEntry, columnIndex);
if (currentEntry > offset)
    textEntry.Text = currentEntry.ToString();
currentEntry++;

EDIT: Based on your comment, first run a method when you create your control to build the grid and populate all the textfields and store them in a listing of some sort:

private int Rows = 2;
private int Columns = 5;
private TextBlock[][] TextEntries;

private void CreateTextBlocks()
{
    TextEntries = new TextBlock[Rows][];
    for (int rowIndex = 0; rowIndex < rows; rowIndex++)
    {
        entries[rowIndex] = new string[columns];
        for (int columnIndex = 0; columnIndex < columns; columnIndex++)
        {
            TextBlock textEntry = new TextBlock();
            Grid.SetRow(textEntry, rowIndex);
            Grid.SetColumn(textEntry, columnIndex);
            myGrid.Children.Add(textEntry);

            TextEntries[rowIndex][columnIndex] = textEntry;
        }
    }
}

Then subsequently run another method to alter the values as desired:

private void fillDate(int offset)
{
    int currentEntry = 1;

    for(int rowIndex = 0; rowIndex < Rows; rowIndex++)
    {
        for (int columnIndex = 0; columnIndex < Columns; columnIndex++)
        {
            TextBlock textEntry = TextEntries[rowIndex][columnIndex]

            if (currentEntry > offset)
                textEntry.Text = currentEntry.ToString();
            else
                textEntry.Text = String.Empty;

            currentEntry++;
        }
    }
}

Upvotes: 0

Related Questions