График OxyPlot не отображается в дочерней сетке - PullRequest
0 голосов
/ 25 ноября 2018

Я делаю статистическое приложение, используя OxyPlot WPF, где пользователь вводит ограничения классов и частоты для каждого класса.Затем вы выбрали, какой из 4 графиков вы хотите отобразить.Затем график отображается в этом белом поле ( см. Изображение ниже ).

Графический интерфейс приложения статистики

В конструкторе MainWindow яустановите this.DataContext = this.У меня есть свойство PlotModel с именем "MyModel", которое связано со свойством Model элемента управления PlotView в коде XAML (<oxy:PlotView Model="{Binding MyModel}"/>).Этот PlotView находится внутри Grid, называемого «График», который находится внутри основного Grid (он находится внизу всего моего кода xaml).

Таким образом, при нажатии кнопки «Показать» внутри ее обработчика событий происходит переход в другой оператор if, в зависимости от того, какой переключатель выбран.В конце каждого оператора if устанавливается this.MyModel равным PlotModel, созданному внутри него.Я думаю, что написав this.MyModel = model, он должен отображать график, но когда я его протестировал, в белой части ничего не отображается ( см. Весь код ниже ).

Я не уверенесли эта проблема связана с тем, что this.MyModel= model находится внутри дочерней сетки, или если есть проблемы с привязкой.

Я относительно новичок в программировании WPF в целом, и любая помощь будет принята.Спасибо!

MainWindow.xaml:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:StatsApp"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    xmlns:oxy="http://oxyplot.org/wpf"
    xmlns:Properties="clr-namespace:StatsApp.Properties" x:Class="StatsApp.MainWindow"
    mc:Ignorable="d"
    Title="Frequency Distribution Graph Generator" Height="450" Width="800">

<Grid Background="Gray">

    <Grid x:Name="Graph" HorizontalAlignment="Left" Height="306" Margin="340,39,0,0" VerticalAlignment="Top" Width="421">
        <oxy:PlotView Model="{Binding MyModel}"/>
    </Grid>

    <!-- I left out all the unnecessary textboxes and buttons ..... -->

</Grid>

MainWindow.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    //private bool isfirstclick = true;

    public PlotModel MyModel { get; private set; }

    private void DisplayBtn_Click(object sender, RoutedEventArgs e)
    {
        // ---------------Retrieving Input START----------------
        TextBox[] lowerLimitsTxtBoxes =
        {
            Lower1TxtBox,
            Lower2TxtBox,
            Lower3TxtBox,
            Lower4TxtBox,
            Lower5TxtBox,
            Lower6TxtBox,
            Lower7TxtBox,
            Lower8TxtBox
        };

        TextBox[] upperLimitsTxtBoxes =
        {
            Upper1TxtBox,
            Upper2TxtBox,
            Upper3TxtBox,
            Upper4TxtBox,
            Upper5TxtBox,
            Upper6TxtBox,
            Upper7TxtBox,
            Upper8TxtBox
        };

        TextBox[] freqsTxtBoxes =
        {
            Freq1TxtBox,
            Freq2TxtBox,
            Freq3TxtBox,
            Freq4TxtBox,
            Freq5TxtBox,
            Freq6TxtBox,
            Freq7TxtBox,
            Freq8TxtBox
        };

        double[] lowerLimits = new double[8];

        for (int i = 0; i < lowerLimits.Length; i++)
        {
            if (Double.TryParse(lowerLimitsTxtBoxes[i].Text, out double lower))
            {
                lowerLimits[i] = lower;
            }
            else
            {
                lowerLimits[i] = -1;
            }
        }


        double[] upperLimits = new double[8];

        for (int i = 0; i < upperLimits.Length; i++)
        {
            if (Double.TryParse(upperLimitsTxtBoxes[i].Text, out double upper))
            {
                upperLimits[i] = upper;
            }
            else
            {
                upperLimits[i] = -1;
            }
        }

        //IMPORTANT -> The array of frequencies
        int[] freqs = new int[8];

        for (int i = 0; i < freqs.Length; i++)
        {
            if (Int32.TryParse(freqsTxtBoxes[i].Text, out int freq))
            {
                freqs[i] = freq;
            }
            else
            {
                freqs[i] = -1;
            }
        }



        int numClasses = 0;

        for (int i = 0; lowerLimits[i] != -1 && i < 8; i++)
        {
            numClasses++;
        }

        if (numClasses < 2)
        {
            throw new ArgumentException("Must use at least 2 classes");
        }

        //IMPORTANT -> The class marks array: double
        double[] classMarks = new double[numClasses];
        for (int i = 0; i < classMarks.Length; i++)
        {
            classMarks[i] = (lowerLimits[i] + upperLimits[i]) / 2.0;
        }

        //IMPORTANT -> The class marks array: string
        string[] classMarksString = new string[numClasses];
        for (int i = 0; i < numClasses; i++)
        {
            classMarksString[i] = classMarks[i] + "";
        }

        //----------Retrieving Input END--------------------


        if ((bool)ScatterRBtn.IsChecked)
        {
            var model = new PlotModel { Title = "Scatter Plot" };
            var scatter = new ScatterSeries { MarkerType = MarkerType.Circle };
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Left,  Title = "Class Marks" });
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Frequency" });

            for ( int i =0; i < numClasses; i++)
            {
                scatter.Points.Add(new ScatterPoint(classMarks[i], freqs[i]));
            }

            model.Series.Add(scatter);

            //This doesn't update the graph even though I binded it in XAML code
            this.MyModel = model;
        }
        else if ((bool)RelativeFqRBtn.IsChecked)
        {
            var model = new PlotModel { Title = "Relative Frequency Polygon" };
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Maximum = 1, Title = "Class Marks" });
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Frequency (%)" });

            var relativeFQ = new LineSeries();

            int frequencyTotal = 0;

            for (int i=0;  i < 8 && freqs[i] != -1 ; i++)
            {
                frequencyTotal += freqs[i];
            }

            for (int i = 0; i < numClasses; i++)
            {
                relativeFQ.Points.Add(new DataPoint(classMarks[i], freqs[i]/frequencyTotal ));
            }

            model.Series.Add(relativeFQ);

            //This doesn't update the graph even though I binded it in XAML code
            this.MyModel = model;
        }
        else if ((bool)CummuFqRBtn.IsChecked)
        {
            var model = new PlotModel { Title = "Cummulative Frequency Polygon" };
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title= "Frequency" });
            model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title ="Class Boundaries" });

            var cummulativeFQ = new LineSeries();

            double[] classBoundaries = new double[numClasses + 1];

            double midpointDistance = (lowerLimits[1] - upperLimits[0]) / 2;

            classBoundaries[0] = lowerLimits[0] - midpointDistance;

            for (int i = 0; i < numClasses; i++)
            {
                classBoundaries[i + 1] = upperLimits[i] + midpointDistance;
            }

            cummulativeFQ.Points.Add(new DataPoint(classBoundaries[0], 0));

            for (int i = 0; i< numClasses ; i++)
            {
                cummulativeFQ.Points.Add(new DataPoint(classBoundaries[i+1], freqs[i]));
            }

            model.Series.Add(cummulativeFQ);

            //This doesn't update the graph even though I binded it in XAML code
            this.MyModel = model;
        }
        else
        {
            var model = new PlotModel { Title = "Histogram" };

            model.Axes.Add(new LinearAxis { Title = "Frequency", Position = AxisPosition.Left });

            model.Axes.Add(new CategoryAxis
            {
                Title = "Class Marks",
                ItemsSource = classMarksString

            });

            var histogram = new ColumnSeries();
            model.Series.Add(histogram);

            for (int i = 0; i < numClasses; i++)
            {
                histogram.Items.Add(new ColumnItem(freqs[i]));
            }

            //This doesn't update the graph even though I binded it in XAML code
            this.MyModel = model;

        }
    }
}

1 Ответ

0 голосов
/ 25 ноября 2018

Быстрое исправление для вашего кода

Вместо <oxy:PlotView Model="{Binding MyModel}"/> используйте <oxy:PlotView x:Name="myPlot"/>

Удалите public PlotModel MyModel { get; private set; } и установите модель сразу после ее создания.

myPlot.Model=model;

PS Не используйте Binding, если вы не знаете, как это работает

...