繁体   English   中英

在卡片中存储数组数据的简单示例

[英]Simple example to store array data in card

我想了解如何使用自适应卡读/写数据。 我可以从提交操作中读取数据,并以文本形式回复,但不确定卡片中的输入数据如何呈现。 首先,我想将 shotValue 添加到我可以在卡的整个生命周期中携带的数组。 有人可以让我知道如何做到这一点吗?

此问题的目的是了解如何保留卡片中的现有响应。 就像在战舰中,我拍摄“A1”,在输入框中输入,提交,我想在卡片中看到“A1”。 我添加“A2”,提交,然后我想在发送给团队的卡片中看到“A1”和“A2”。 我知道我需要在每次拍摄时从头开始重建卡片,这意味着,我需要在每个动作中以某种方式进行拍摄。

数据卡:

{
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "TextBlock",
      "text": "Hello {name}"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "stretch",
          "id": "",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "Input.Text",
                  "placeholder": "Voorbeeld: A1",
                  "id": "id_shoot",
                  "$data": "shoot"
                }
              ]
            }
          ]
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "TextBlock",
                  "text": " {shoot}",
                  "horizontalAlignment": "Right",
                  "id": ""
                }
              ],
              "$data": "{shoots}",
              "id": "shotcoords"
            }
          ],
          "$data": "{shots}"
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "{status}",
                  "id": ""
                }
              ],
              "$data": "{shoots}",
              "id": "shotstatuses"
            }
          ],
          "id": ""
        }
      ]
    },
    {
      "type": "ActionSet",
      "id": "",
      "actions": [
        {
          "type": "Action.Submit",
          "title": "Shoot",
          "id": "",
          "style": "positive",
          "data": {}
        }
      ]
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}

数据

{
  "name": "Test shot",
  "shoots": [
    {
      "shoot": "a1",
      "status": "hit"
    },
    {
      "shoot": "a2",
      "status": "hit"
    }
  ]
}

没有“简单”的方法可以做到这一点,但有一种方法。 答案将与类似。

首先,您需要一种保存卡片状态的方法,以便您可以更新卡片的活动。 在 C# 中,您可以像这样声明状态属性访问器:

public IStatePropertyAccessor<Dictionary<string, (string ActivityId, List<string> Shots)>> BattleshipStateAccessor { get; internal set; }

然后你可以像这样实例化它

BattleshipStateAccessor = _conversationState.CreateProperty<Dictionary<string, (string, List<string>)>>("battleshipState");

您需要在这里做出一些决定。 首先,我选择将 state 属性设为字典,以便我可以跟踪多张卡片,并且只更新被点击的特定卡片。 如果您不关心这个,那么您就不需要字典,也不需要担心“卡 ID”,但至少需要保存一个活动 ID,以便您可以更新卡. 至于保存“镜头”,您在这里有几个选择。 您可以通过更新每次拍摄的提交操作的数据来在客户端保存该状态,但我认为我最好将拍摄保存在机器人状态,因为无论如何我已经需要将活动 ID 保存在机器人状态。 然后是关于您应该保存关于每个镜头的哪些信息的问题。 在这个例子中,我只保存用户输入的镜头的位置,而不是镜头的状态,因为我认为我总是可以在需要时重新计算状态。

我已将您的提交操作修改为如下所示:

{
  "type": "Action.Submit",
  "title": "Shoot",
  "style": "positive",
  "data": {
    "behavior": "Shoot",
    "cardId": ""
  }
}

我在这里所做的是向您的数据对象添加了两个属性,这些数据将与文本输入的值一起发送到您的机器人。 “行为”属性将帮助您的机器人路由到正确的功能,以防您的机器人使用多种可以以不同方式处理的动作。 “cardId”属性只是一个占位符,您的机器人代码将在创建卡片时填写。 我已将这些属性的名称存储在常量KEYBEHAVIORKEYCARDID

您需要一种一致的方式来生成您的卡片,您可以在最初发送卡片和更新卡片时使用这种方法。

internal static IMessageActivity CreateBattleshipCardActivity(
    string cardId,
    object data = null)
{
    data = data ?? new
    {
        name = "Test shot",
        shoots = new string[0],
    };

    JObject card = CreateAdaptiveCard("battleship", data);

    foreach (var token in card.Descendants()
        .Select(token => token as JProperty)
        .Where(token => token?.Name == KEYCARDID))
    {
        token.Value = cardId;
    }

    return MessageFactory.Attachment(new Attachment(
        AdaptiveCard.ContentType,
        content: card));
}

CreateAdaptiveCard函数从具有给定名称的文件中加载 JSON 模板,使用给定数据对其进行转换,并将其反序列化为JObject

使用此函数,您可以在 C# 中像这样最初发送卡片:

public async Task TestBattleshipAsync(
    ITurnContext turnContext,
    CancellationToken cancellationToken)
{
    var activity = turnContext.Activity;
    var cardId = Guid.NewGuid().ToString();
    var reply = CreateBattleshipCardActivity(cardId);
    var response = await turnContext.SendActivityAsync(reply, cancellationToken);
    var dict = await BattleshipStateAccessor.GetAsync(
        turnContext,
        () => new Dictionary<string, (string, List<string>)>(),
        cancellationToken);

    dict[cardId] = (response.Id, new List<string>());
}

您可以更新卡片以响应卡片的“拍摄”提交操作,如下所示:

private async Task ShootAsync(
    ITurnContext turnContext,
    CancellationToken cancellationToken)
{
    var activity = turnContext.Activity;

    if (activity.ChannelId == Channels.Msteams)
    {
        var value = JObject.FromObject(activity.Value);
        var cardId = Convert.ToString(value[BotUtil.KEYCARDID]);
        var dict = await BattleshipStateAccessor.GetAsync(
            turnContext,
            () => new Dictionary<string, (string, List<string>)>(),
            cancellationToken);

        if (dict.TryGetValue(cardId, out var savedInfo))
        {
            savedInfo.Shots.Add(value["id_shoot"].ToString());

            var data = new
            {
                name = "Test shot",
                shoots = savedInfo.Shots.Select(shot => new
                {
                    shoot = shot,
                    status = DetermineHit(shot),
                }),
            };

            var update = CreateBattleshipCardActivity(cardId, data);

            update.Id = savedInfo.ActivityId;
            update.Conversation = activity.Conversation;

            await turnContext.UpdateActivityAsync(update, cancellationToken);
        }
    }
}

自适应卡

暂无
暂无

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

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