绑定可能具有空父级的嵌套属性的数据

10

我希望对 Room.ToNorth.ImageName 进行数据绑定,而 ToNorth 可能为空。

我正在尝试编写自己的文本冒险游戏,并在每个玩家可以前往的方向旁边放置图像(例如开/关门,通道)。当某个方向没有房间时,我将控件绑定到显示“无出口”图像,这对于四个方向都有出口的起始位置很有效,但是当有一个方向为 null 时,我会收到以下异常:

System.ArgumentNullException: 'Value cannot be null. Parameter name: component'

这在新游戏上不是问题,但我正在制作随机生成的地牢,因此在加载游戏时无法保证。我意识到我可能可以通过创建安全空间来弥补此问题,同时设置绑定,然后将玩家移动到他们需要去的地方,但是否有更好的处理方法呢?

我找到了 这个问题 最接近的答案,但由于绑定的方式不同,我不确定能否应用它。

private GameSession _CurrentGame;
private BindingSource _BindToPlayer = new BindingSource();

private void BtnNewGame_Click(object sender, EventArgs e)
{
    _CurrentGame = new GameSession();

    _BindToPlayer.DataSource = _CurrentGame.CurrentPlayer;

    PicBoxNorth.DataBindings.Add("ImageLocation", _BindToPlayer, 
        "CurrentRoom.ToNorth.ImageName", true, DataSourceUpdateMode.OnPropertyChanged, 
        "Images\\Wall.png");
}

ToNorth属性只是从出口数组中获取对象,但如果像上面的链接中建议的那样告诉它返回一个空的出口,那么会存在一个问题,因为该出口将没有任何房间连接,因此很可能无法初始化并抛出异常。更好地解释一下,我的房间设置如下:

public Class Room
{
   public int ID { get; set; }
    public String Name { get; set; }
    public String Description { get; set; }
    public String FarDescription { get; set; }
    public CoOrds Co_Ords { get; set; }

    public Boolean UniqueRoom { get; set; }

    public Exit[] ExitArr { get; set; }

    public Exit ToNorth => ExitArr[0];
    public Exit ToSouth => ExitArr[1];
    public Exit ToWest => ExitArr[2];
    public Exit ToEast => ExitArr[3];
    public Exit ToUp => ExitArr[4];
    public Exit ToDown => ExitArr[5];

    public Exit ToIn => ExitArr[6];
    public Exit ToOut => ExitArr[7];

    public Room(int id, String name, String desc, String fardesc,bool unique = false)
    {
        ID = id;
        Name = name;
        Description = desc;
        FarDescription = fardesc;
        Co_Ords = new CoOrds();
        ExitArr = new Exit[8];

        UniqueRoom = unique;

    }

我的出口设置如下所示

public class Exit
{
    public String Description {get;}         

    public Room RoomA { get; set; }
    public Room RoomB { get; set; }

    public Boolean CanExitA { get; set; } = true;
    public Boolean CanExitB { get; set; } = true;

    public Room NextRoom
    {
        get
        {

            if (RoomA.PlayerHere && CanExitA)
            { return RoomB; }
            else if (RoomB.PlayerHere && CanExitB)
            { return RoomA; }
            else
                return null;
        }
    }

    public String ImageName
    {
        get
        {
            string imagePath = "Images\\";
            if (DoorHere != null)
            {
                return imagePath + DoorHere.ImageName;
            }
            else
                return imagePath + "Pathway.png";
        }

    }

    public Door DoorHere { get; set; }

    public Exit(Room roomA, int Adir, Room roomB, int Bdir, Door door = null)
    {
        RoomA = roomA;
        RoomA.ExitArr[Adir] = this;
        RoomB = roomB;
        RoomB.ExitArr[Bdir] = this;
        DoorHere = door;

    }

门只是一个未命名的对象,具有一些布尔类型的属性,例如IsOpen、IsLocked等,如果您想测试,则不需要它,但出口是匿名创建的,并将自己添加到连接房间中的Exit数组中,因此创建空出口会失败。

任何建议都将不胜感激。


你的实现中提供示例代码会非常有帮助。你可以使用空列表代替null,这可能会消除数据绑定问题。 - Mightee
哪一行代码引发了异常? - Rufus L
没问题,Mightee。我认为我添加的内容足够了,我已经更新了我的房间和出口实现,这样你就可以看到它们是如何连接的。 - Rowie
我得到的错误出现在 PicBoxNorth.DataBindings... 这一行。就像我说的,只要运行这一行时有东西存在,那么它就没问题,并且之后也不会被 null 所干扰(它会显示 Wall.png)。 - Rowie
在这种情况下,我会认为列表被填充了 null 而不是空的,如果不是这样,我该如何检查? - Rowie
1个回答

4
作为一种选择,您可以创建一个属性来进行空值检查,并使用该属性获取/设置第二级属性。
例如,在您的代码中,您可以在Room类中创建ToNorthImageName属性来获取/设置ToNorth.ImageName的值:
public string ToNorthImageName
{
    get { return ToNorth?.ImageName }
    //set { if (ToNorth != null) ToNorth.ImageName = value; }
}

属性 setter 是可选的,如果你只想读取图像名称,则可以将其删除。

然后设置数据绑定到该属性:

PicBoxNorth.DataBindings.Add("ImageLocation", _BindToPlayer, "ToNorthImageName",
    true, DataSourceUpdateMode.OnPropertyChanged);

我正要澄清你的意思,但你已经编辑过了,不过那也可以。谢谢! - Rowie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接