У меня есть линейная диаграмма http://www.chartjs.org/docs/#line- Введение в диаграмму Я хочу заполнить данными из модели представления в MVC6 / Razor

Мои Viewmodels являются

public class LeaderboardViewModel
{
    public List<LeaderboardViewEntry> LeaderboardViewEntries { get; set; }
    public HistoicPointsViewModel HistoicPoints { get; set; } 
}

public class HistoicPointsViewModel
{
    public HistoicPointsViewModel()
    {
        PlayerHistores = new List<PlayerHistoricViewModel>();
    }

    public DateTime[] YAxisDates { get; set; }
    public List<PlayerHistoricViewModel> PlayerHistores { get; set; } 
}

public class PlayerHistoricViewModel
{
    public PlayerHistoricViewModel()
    {
        Points = new List<int?>();
    }

    public string PlayerName { get; set; }
    public List<int?> Points { get; set; }
}

И мой взгляд это раздел сценария в моем представлении:

@model Foosball9001.ViewModels.Leaderboards.LeaderboardViewModel

<canvas id="myChart" width="800" height="400"></canvas>
@section Scripts{
<script type="text/javascript">
    var data = {
        labels: @Model.HistoicPoints.YAxisDates,
        datasets: [
            {
                @foreach (PlayerHistoricViewModel x in Model.HistoicPoints.PlayerHistores)
                {
                    {
                        label: x.PlayerName,
                        fillColor: "rgba(220,220,220,0.2)",
                        strokeColor: "rgba(220,220,220,1)",
                        pointColor: "rgba(220,220,220,1)",
                        pointStrokeColor: "#fff",
                        pointHighlightFill: "#fff",
                        pointHighlightStroke: "rgba(220,220,220,1)",
                        data: x.Points
                    }
                }

            }
        ]
    };

    var ctx = document.getElementById("myChart").getContext("2d");
    var myNewChart = new Chart(ctx).Line(data);
</script>
}

Поэтому я хочу использовать мой HistoicPointsViewModel.YAxisDates в качестве координат оси Y, а затем я хочу создать набор данных для каждого игрока в моем PlayerHistores, где он берет данные из PlayerHistoricViewModel.Points в качестве данных для отображения на графике

Моя проблема заключается в написании динамического JavaScript с использованием Razor, так что это выглядит как пример

var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
    {
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.2)",
        strokeColor: "rgba(220,220,220,1)",
        pointColor: "rgba(220,220,220,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(220,220,220,1)",
        data: [65, 59, 80, 81, 56, 55, 40]
    },
    {
        label: "My Second dataset",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: [28, 48, 40, 19, 86, 27, 90]
    }
]
};
3
Mech0z 17 Дек 2015 в 22:57

3 ответа

Лучший ответ

Я думаю, что самый простой способ - создать соответствующий ChartModel, который можно сериализовать в нужную вам структуру JSON:

public class DtatsetModel
{
    public string label {get;set;}
    public const string fillColor = "rgba(220,220,220,0.2)";
    public const string strokeColor = "rgba(220,220,220,1)";
    public const string pointColor = "rgba(220,220,220,1)";
    public const string pointStrokeColor = "#fff";
    public const string pointHighlightFill = "#fff";
    public const string pointHighlightStroke = "rgba(151,187,205,1)";
    public List<string> data {get;set;}

    public DtatsetModel(PlayerHistoricViewModel x)
    {
        this.label = x.PlayerName;
        this.data =  x.Points.Where(p=>p.HasValue).Select(p=>p.ToString());
    }
}

public class ChartModel
{
   public List<string> labels {get;set;}
   public List<DtatsetModel> datasets {get;set;}

   public ChartModel(HistoicPointsViewModel x)
   {
      this.labels = x.Select(d=>d.ToString("MMMM"));
      this.datasets = x.PlayerHistores.Select(h=>new DtatsetModel(h));
   }
}

То в представлении вы можете сделать что-то вроде

<script type="text/javascript">
    var data = @Html.Raw(JsonConvert.SerializeObject(new ChartModel(Model.HistoicPoints)))
    var ctx = document.getElementById("myChart").getContext("2d");
    var myNewChart = new Chart(ctx).Line(data);
</script>

Для сериализации я использовал JSON.NET

3
Alex Art. 17 Дек 2015 в 20:43

Вам нужно закодировать список моделей в json, вы можете сделать это с помощью json helper от razor, попробуйте это:

var datelist = @Html.Raw(Json.Encode(Model.HistoicPoints.YAxisDates.Select(v => v.ToString("MMMM")));

ToString("MMMM") даст вам полное название месяца.

То же самое для игрока исторического

var playerHistory = @Html.Raw(Json.Encode(Model.HistoicPoints.PlayerHistores.Select(v => new
{
    label = v.PlayerName,
    fillColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    strokeColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    pointColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    pointStrokeColor = "#fff",
    pointHighlightFill = "#fff",
    pointHighlightStroke = "rgba(220,220,220,1)",
    data = v.Points
})));

Я создал цвета, используя класс Color, если вы хотите использовать его или просто установите rgba в виде строки.

И в основном вы делаете это в коде JavaScript.

var data = {
    labels: '@datelist',
    datasets: '@playerHistory'
};
1
Overmachine 17 Дек 2015 в 21:02

Прежде всего, я бы предложил не смешивать javascript и razor, поскольку встроенный javascript склонен к XSS.

Я бы использовал атрибуты данных на некоторых невидимых элементах, которые вы можете создать в бритве, а затем прочитал бы эти атрибуты данных из javascript.

Поэтому просто создайте элементы div с атрибутами данных (описание атрибутов данных )

            @foreach (PlayerHistoricViewModel x in Model.HistoicPoints.PlayerHistores)
            {
                <div
                    class="players"
                    data-label= "x.PlayerName",
                    data-fillColor= "rgba(220,220,220,0.2)",
                    data-strokeColor= "rgba(220,220,220,1)",
                    data-pointColor= "rgba(220,220,220,1)",
                    data-pointStrokeColor= "#fff",
                    data-pointHighlightFill= "#fff",
                    data-pointHighlightStroke= "rgba(220,220,220,1)",
                    data-points= "x.Points"//this will maybe need some work to make json array
                />
            }

И в javascript:

var datasets = [];
$("div.players").each(function(){
    var testdata = {
              label = $(this).data('label');
              fillColor = $(this).data('label');
              ...
              points = $(this).data('points');
              //if datapoints will be json array then it will be automatically parsed as such
     }

    datasets.push(testdata);
});

Таким образом, вы отделили JavaScript от бритвы.

1
Mateusz 17 Дек 2015 в 20:48