易于访问的控件数组

时间:2012-09-05 16:06:51

标签: c# wpf xaml microsoft-metro

我对整个XAML事情都很陌生。

我需要使用常量行数和列数(例如2x5)创建一个表(网格),并在每个单元格中放置一个TextBlock

我该如何正确地做到这一点,以便我可以轻松更改细胞数据?

例如,我想创建一个接受1个整数作为offset的函数:

void fillDate(int offset)

并逐渐从偏移量开始填充单元格。

即。使用`fillData(3)'为2x5调用该函数将生成下表:

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

2 个答案:

答案 0 :(得分:2)

试试这个。在这里,您使用 ListBox 作为items数组的容器,使用 UniformGrid 作为占位符(您可以将行数和列数绑定到类的属性以在运行时更改它们)

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

并且在代码中您只需要更改集合的元素

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

答案 1 :(得分:0)

没什么特别的,来自Silverlight / XAML背景,但可能或多或少都有效。您可能需要调整轻微的API差异(在没有VS方便的情况下使用记事本编写)和未经测试,但应该为您提供开始所需的内容。

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

编辑:刚刚意识到你可能想要一个没有文本的TextBlock在“空”单元格中,在这种情况下用内部循环代码替换:

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

编辑:根据您的评论,首先在创建控件时运行一个方法来构建网格并填充所有文本字段并将它们存储在某种类型的列表中:

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

然后运行另一个方法来根据需要改变值:

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