简体   繁体   English

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

[英]Data binding to a nested property with possibly null parent

I want to perform data-binding to Room.ToNorth.ImageName while ToNorth may be null. 我想对Room.ToNorth.ImageName执行数据绑定,而ToNorth可能为null。

I'm trying to write my own text adventure and have images next to each of the directions a player can go (ie. open/closed door, pathway). 我正在尝试编写自己的文本冒险,并在玩家可以去的每个方向旁边放置图像(即打开/关闭门,通道)。 When there isn't a room in a given direction I have the controls bound to show a 'no exit' image, this works great so long the player starting location has an exit in all 4 directions, however when one is null I get the following exception 当在给定方向上没有房间时,我有控件绑定显示“无退出”图像,这很有效,所以玩家起始位置在所有4个方向都有一个出口,但是当一个为空时,我得到了以下例外

System.ArgumentNullException: 'Value cannot be null. System.ArgumentNullException:'值不能为null。 Parameter name: component' 参数名称:component'

This is isn't an issue on a new game but I'm making randomly generated dungeons so it can't be guaranteed on a load game. 这不是一个新游戏的问题,但我正在制作随机生成的地下城,所以在加载游戏中无法保证。 I realise I could probably fudge it by creating a safe space while the bindings are set then moving the player to where they need to be but is there a proper way to handle this? 我意识到我可以通过创建一个安全的空间,然后设置绑定,然后将播放器移动到他们需要的位置,但有没有一个正确的方法来处理它?

The closest answer I've found is this question , but I'm not sure I can apply it here due to how it's bound. 我找到的最接近的答案是这个问题 ,但我不确定我是否可以在这里应用它,因为它受到了限制。

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

The ToNorth property just gets the object from an an array of exits, but telling it to return an empty exit if it's null (like suggested in the above link) would be problematic in that the exit wouldn't have any rooms to connect to and thus fail to initialise likely throwing an exception itself along the way. ToNorth属性只是从一个出口数组中获取对象,但如果它为null(如上面的链接中所示),则告诉它返回一个空出口将会出现问题,因为出口没有任何连接的房间和因此无法初始化可能会在此过程中抛出异常。 To explain better, I have my rooms set up as follows 为了更好地解释,我的房间设置如下

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;

    }

And my exits are set up like so 我的出口就是这样设置的

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;

    }

Door is just an unnamed object with a few bools for IsOpen, IsLocked etc. and shouldn't be needed if you want to test this but exits are created anonymously and add themselves to the Exit array in both connecting rooms, hence creating empty ones would fail. 门只是一个未命名的对象,有一些用于IsOpen,IsLocked等的bool,如果你想测试它,不应该需要,但是匿名创建出口并将它们自己添加到两个连接房间的Exit数组,因此创建空的将失败。

Any suggestions would be greatly appreciated. 任何建议将不胜感激。

As an option, you can create a property to do null-checking and get/set second level property using that property. 作为选项,您可以创建一个属性来执行空检查,并使用该属性获取/设置二级属性。

For example in your code, you can create ToNorthImageName property to get/set the value of ToNorth.ImageName in Room class: 例如,在您的代码中,您可以创建ToNorthImageName属性以获取/设置Room类中的ToNorth.ImageName的值:

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

The property setter is optional, you can remove it if you just want to read the image name. 属性设置器是可选的,如果您只想读取图像名称,可以将其删除。

Then setup data-binding to that property: 然后设置数据绑定到该属性:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM