0

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

例如 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 更改为从每个统计数据(c.Stats)创建的二维数组。

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

有没有更高效的解决方案?或者有谁知道为什么我会收到 DataGrid2D 的路径错误?

4

3 回答 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 不使用这些统计属性的原因是它们彼此分开。它不知道如何根据几个不同的属性创建行。

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

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

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

字符类如下所示:

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

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

祝你好运

U_U

于 2012-12-14T14:12:30.013 回答
0

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

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

于 2012-12-14T11:10:06.193 回答
0

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

对于我也有一个固定数量并想要一个双向绑定的点,我定义了一个固定数量的 Columns 和 Rows,并将 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>

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

于 2012-12-14T13:06:20.460 回答