数据绑定到嵌套属性,可能为null父级

Row*_*wie 7 .net c# data-binding winforms

我想执行数据绑定,Room.ToNorth.ImageName而while ToNorth可能为null.

我正在尝试编写自己的文本冒险,并且在玩家可以前往的每个方向旁边都有图像(即打开/关闭的门,通道).当在给定方向上没有房间时,我有控件绑定显示"无退出"图像,这很有效,所以玩家起始位置在所有4个方向都有一个出口,但是当一个为空时,我得到了以下例外

System.ArgumentNullException:'值不能为null.参数名称: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");
}
Run Code Online (Sandbox Code Playgroud)

ToNorth属性只是从一个出口数组中获取对象,但如果它为null(如上面的链接中所示),则告诉它返回一个空出口将会出现问题,因为出口没有任何连接的房间和因此无法初始化可能会在此过程中抛出异常.为了更好地解释,我的房间设置如下

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;

    }
Run Code Online (Sandbox Code Playgroud)

我的出口就是这样设置的

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;

    }
Run Code Online (Sandbox Code Playgroud)

门只是一个未命名的对象,有一些用于IsOpen,IsLocked等的bool,如果你想测试它,不应该需要,但是匿名创建出口并将它们自己添加到两个连接房间的Exit数组中,因此创建空的将失败.

任何建议将不胜感激.

Rez*_*aei 4

作为一个选项,您可以创建一个属性来执行空检查并使用该属性获取/设置第二级属性。

例如,在您的代码中,您可以创建属性来获取/设置类中ToNorthImageName的值:ToNorth.ImageNameRoom

public string ToNorthImageName
{
    get { return ToNorth?.ImageName }
    //set { if (ToNorth != null) ToNorth.ImageName = value; }
}
Run Code Online (Sandbox Code Playgroud)

属性设置器是可选的,如果您只想读取图像名称,可以将其删除。

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

PicBoxNorth.DataBindings.Add("ImageLocation", _BindToPlayer, "ToNorthImageName",
    true, DataSourceUpdateMode.OnPropertyChanged);
Run Code Online (Sandbox Code Playgroud)