如何将多个数组绑定到DataGrid

时间:2012-12-14 11:03:53

标签: c# wpf data-binding datagrid

我有一个角色对象,其中我有10个阵列,代表10个角色的统计数据(敏捷,力量等 - 这是一个角色扮演游戏)。阵列跟踪统计数据并随着时间的推移逐渐增加,因此我知道他们在哪个级别增加了哪个统计数据。数组是有限的,我跟踪到50级,所以我不需要能够跟踪可变数量的行或列。一切都是固定的。

e.g。 string [] Agility = new string [50];

我想在DataGrid中显示此信息,并将每行中的每个单元格绑定到每个stat数组的元素。我发现并尝试了我认为最好的希望,一个名为DataGrid2D的库,但是无法让我尽力而为。当我尝试更改DataGrid中的值时,我会收到错误:双向绑定需要Path或XPath。当我从ListBox中选择角色时,填充了10x50网格,甚至需要花费几秒钟来填充。

在此处找到了DataGrid2D示例:How to populate a WPF grid based on a 2-dimensional array。我使用了Meleak的答案(第二个下来),更改了m_intArray,用于从每个统计数据创建的2D数组(c.Stats)。

var c = CE_Characters_charactersLB.SelectedItem as Character;
var dg = CE_Characters_statsDG;
dg.ItemsSource = GetBindable2DArray<string>(c.Stats);

是否有更高效的解决方案?或者有人知道我为什么用DataGrid2D得到Path错误吗?

4 个答案:

答案 0 :(得分:0)

从您发布的链接:“它是DataGrid的子类,并添加一个名为ItemsSource2D的属性,用于绑定2D或1D源”

所以我猜你必须使用该库提供的DataGrid并使用ItemsSource2D属性

答案 1 :(得分:0)

我问了similar question

我瘦你的意思是敏捷= {10,5}和强度= {5,10}会指定一个快速弱的角色和一个相对强烈的缓慢角色。

class   Stat
{
    public Int Agility  { get; set; }
    public Int Strength { get; set; }
    public Int HorseArmour { get; set; }

    public Stat()
    {
        //Constructor
    }

}

Public ObservableCollection<Stat>  Stats { get; set; } //or list, but we'll be binding in a minute

 Binding="{Binding Path=Agility}" //(agility being an example)
如果您在xam中设置列,则

为您的列。 这在你的数据网格上:

 ItemsSource="{Binding}"

答案 2 :(得分:0)

我有类似的问题,请看我的帖子: Two Way EntityCollection Binding to a Two Dimension Data Matrix

对于我也有一个固定的amout并想要一个TwoWay Binding,我定义了一个固定的Columns和Rout,并将Column和Row属性动态分配给ItemsControl中的TextBlock。

继承守则

<ItemsControl ItemsSource="{Binding Path=CustomerTankDayStructure,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                              Grid.Column="1"
                                              Grid.Row="2">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <Grid helper:EnterKeyTraversal.IsEnabled="True"
                                                  KeyboardNavigation.TabNavigation="Local">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="0" />
                                                    [...]
                                                    <ColumnDefinition Width="30" />
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="0" />
                                                    <RowDefinition Height="30" />
                                                    [...]
                                                    <RowDefinition Height="30" />
                                                </Grid.RowDefinitions>
                                            </Grid>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemContainerStyle>
                                        <Style>
                                            <Setter Property="Grid.Column" Value="{Binding Path=DoW}" />
                                            <Setter Property="Grid.Row" Value="{Binding Path=HoD}" />
                                        </Style>
                                    </ItemsControl.ItemContainerStyle>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <Border BorderThickness="0,0,1,1"
                                                    Style="{StaticResource ResourceKey=DefaultBorder}">
                                                <TextBox BorderThickness="0"
                                                         MaxLength="3"
                                                         Style="{StaticResource ResourceKey=EditableTextBoxWithoutWarningForTanks}"
                                                         TextAlignment="Center"
                                                         VerticalContentAlignment="Center"
                                                         IsTabStop="True">
                                                    <TextBox.TabIndex>
                                                        <MultiBinding Converter="{StaticResource ResourceKey=CustomerTankTabIndexConverter}">
                                                            <Binding Path="DoW" />
                                                            <Binding Path="HoD" />
                                                        </MultiBinding>
                                                    </TextBox.TabIndex>
                                                    <TextBox.Text>
                                                        <Binding Path="Value"
                                                                 Mode="TwoWay"
                                                                 NotifyOnValidationError="True"
                                                                 TargetNullValue=""
                                                                 UpdateSourceTrigger="PropertyChanged">
                                                            <Binding.ValidationRules>
                                                                <validator:Int32Validator Mandatory="True" 
                                                                                          Min="0" 
                                                                                          Max="100" />
                                                            </Binding.ValidationRules>
                                                        </Binding>

                                                    </TextBox.Text>
                                                </TextBox>
                                            </Border>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>

它有点“脏代码”,但对于这个问题,我没有找到任何其他解决方案:)

答案 3 :(得分:0)

我花了很长时间才弄清楚你的计划无法正常运作的原因。

基本上如果我是正确的,你的角色类看起来像这样:

public class Character
{
      public string Name { get; set; }
      public int Level { get; set; }          
      public int[] Agility { get; set; }         
      public int[] Strength { get; set; }         
      public int[] Stamina { get; set; }         
      public int[] Intelligence { get; set; }
}

Datagrid不使用这些stat属性的原因,因为它们彼此分开。它不知道如何基于几个不同的属性创建行。

正如Nathan Cooper之前所指出的,你真正需要的是另一个名为Stat(或类似的东西)的类,它可以将每个属性作为整数存储。然后,您需要这些类的集合来绑定您的数据网格。

这样想。您目前将数据垂直分组到列中。 Datagrids用于将数据分组为行。所以你需要一组代表一行的对象。

我花时间创建了一个示例应用程序,它将显示该概念的工作原理。

角色类看起来像这样:

 public class Character
 {
    public string Name { get; set; }

    public int Level { get; set; }

    public List<Stat> Stats { get; set; }

    public Character()
    {

    }

    public class Stat
    {
        public int Agility { get; set; }
        public int Strength { get; set; }
        public int Intelligence { get; set; }
        public int Stamina { get; set; }
    }
}

在这里你可以看到我创建了一个类似于Nathan所说的Stat类。就像我说的那样,这个类将包含数据网格的“行”,因此数据可以按照数据网格易于理解的方式进行分组。

表单的XAML如下所示:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>

    <ComboBox Margin="5,5,5,5" DisplayMemberPath="Name" Grid.Row="0"  ItemsSource="{Binding Path=Characters}"  SelectedItem="{Binding Path=SelectedCharacter}"></ComboBox>
    <DataGrid Grid.Row="1" Margin="5,5,5,5" AutoGenerateColumns="True" ItemsSource="{Binding Path=SelectedCharacter.Stats}" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Agility" Binding="{Binding Path=Agility}"></DataGridTextColumn>
            <DataGridTextColumn Header="Strength" Binding="{Binding Path=Strength}"></DataGridTextColumn>
            <DataGridTextColumn Header="Intelligence" Binding="{Binding Path=Intelligence}"></DataGridTextColumn>
            <DataGridTextColumn Header="Stamina" Binding="{Binding Path=Stamina}"></DataGridTextColumn>
        </DataGrid.Columns>

    </DataGrid>
</Grid>

我创建了一个组合框,它将选择要在DataGrid中显示的字符。此字符统计信息绑定到数据网格的列。

最后这里是ViewModel(不确定你是否正在使用MVVM,但是你应该这么做。无论如何,这些代码可以放在后面的代码中,几乎不需要更改):

public class MainWindowViewModel:ViewModelBase
{
    private IList<Character> _characters;
    public IList<Character> Characters
    {
        get
        {
            return _characters;
        }
        set
        {
            _characters = value;
            RaisePropertyChanged(()=>Characters);
        }
    }

    private Character _character;
    public Character SelectedCharacter
    {
        get
        {
            return _character;
        }
        set
        {
            _character = value;
            RaisePropertyChanged(()=>SelectedCharacter);
        }
    }

    public MainWindowViewModel()
    {
        InitializeCharacters();
    }

    private void InitializeCharacters()
    {
        Characters = new List<Character>();
        SelectedCharacter = new Character();
        Characters.Add(new Character
        {
            Name = "Tank",
            Level = 3,
            Stats = new List<Character.Stat>()
            {
                new Character.Stat()
                {
                    Agility =       10,
                    Intelligence =  8, 
                    Strength =      14,
                    Stamina =       16
                },

                    new Character.Stat()
                {
                    Agility =      11,
                    Intelligence = 9, 
                    Strength =     16,
                    Stamina =      18
                },

                    new Character.Stat()
                {
                    Agility =       12,
                    Intelligence = 10, 
                    Strength =      17,
                    Stamina =       20
                }
            }



        });

        Characters.Add(new Character 
        { 
            Name = "Healer", 
            Level = 4, 

              Stats = new List<Character.Stat>()
            {
                new Character.Stat()
                {
                    Agility =       10,
                    Intelligence =  14,
                    Strength =       8,
                    Stamina =       10
                },

                    new Character.Stat()
                {
                    Agility =      11,
                    Intelligence = 16,
                    Strength =     9, 
                    Stamina =      11
                },

                    new Character.Stat()
                {
                    Agility =      12,
                    Intelligence = 17,
                    Strength =    10, 
                    Stamina =      13
                },
                    new Character.Stat()
                {
                    Agility =       14,
                    Intelligence =  20,
                    Strength =     10, 
                    Stamina =       14
                }
            }
        });

        Characters.Add(new Character 
        { 
            Name = "Ranger", 
            Level = 6,  

            Stats = new List<Character.Stat>()
            {
                new Character.Stat()
                {
                    Agility =        12,
                    Intelligence =   8, 
                    Strength =       10,
                    Stamina =        8
                },

                    new Character.Stat()
                {
                    Agility =      14,
                    Intelligence = 9,
                    Strength =     11,
                    Stamina =     10
                },

                    new Character.Stat()
                {
                    Agility =       17,
                    Intelligence = 10, 
                    Strength =     12,
                    Stamina =      11
                },
                    new Character.Stat()
                {
                    Agility =      18,
                    Intelligence =11,
                    Strength =    13,
                    Stamina =     12
                },

                    new Character.Stat()
                {
                    Agility =       20,
                    Intelligence = 12,
                    Strength =     15,
                    Stamina =      13
                },
                    new Character.Stat()
                {
                    Agility =      22,
                    Intelligence = 13,
                    Strength =     16,
                    Stamina =      13
                }
            }
        });

    }


}

ViewModel中的大部分空间都由我创建虚拟数据,所以如果您愿意,可以随意删除它。重要的部分是创建SelectedCharacter和Characters Classes。

这是项目的链接,因此您可以看到它的实际效果。 (请原谅我名字不好的名字) https://docs.google.com/open?id=0B9JOiSJxT9vjZVl1SHd3UzBiZEE

祝你好运

U_U