locked
Adding libraries and use them?

    Question

  • First of all, I need to thank you guys for having helped me the last couple months.  I'm a structure engineer trying to fumble my way through the world of programming.  Because of your help, I've published a few apps and people are actually buying them.  Who would have thunk?

    I'm trying to add a plotting library called oxyplot.  I'm trying to add the metro library.  I'm using xaml/c++.  But it won't add because of incompatibility.  I tried 2 different ways, both failed.  Here are the screenshots.  Could you please tell me what is wrong and how I can resolve this issue?

    https://dl.dropboxusercontent.com/u/34225393/ploterror.png

    https://dl.dropboxusercontent.com/u/34225393/ploterror1.png

    Secondly, once I've added a library, how do I use it in my app?  Like do I reference it like a usercontrol?

    Thursday, August 8, 2013 3:49 PM

Answers

  • I'm not familiar with Oxyplot, but from the screenshot and a quick glance at http://oxyplot.codeplex.com/ it looks like OxyPlot is a .Net Portable Class Library (PCL) rather than a Windows Runtime Component. If that is correct it can be called only from .Net, not from C++/Cx.

    You might want to ask on the OxyPlot site to confirm.

    You could create your own Windows Runtime Component in C# which wraps and exposes OxyPlot's PCL.

    --Rob

    Thursday, August 8, 2013 4:31 PM
    Owner
  • I was able to cobble something together as a learning challenge for myself.  There may be a better way to do it and, if so, I hope someone provides a better solution.  So here goes....

    You can install OxyPlot in a C# project because it is based on .Net   So my solution is to create a Windows Runtime Component based on C# and including OxyPlot.  The component will consist of a UserControl that you can add to your C++/XAML project.  The C++ code can send data to the UserControl for plotting.

    Here are the steps:

    1. Create a new solution/project based on the C# Windows Runtime Component.  I called mine "OxyPlotWrapper".

    2. Use the Nuget Package Manager Console to install OxyPlot for Metro.

    3. Save the solution.

    4. Load your C++/XAML project into VS

    5. In the Solution Explorer, right click on the Solution and then select Add Existing Project

    6. Browse to your OxyPlotWrapper solution and find the OxyPlotWrapper.csproj and click Open.  It should now show up as a new project in your solution.

    7. In the Solution Explorer, right click on the C++/XAML project and select References then Add New Reference then in Projects Tab find OxyPlotWrapper and click the checkbox then OK.

    8. Now in the Solution Explorer, right click on the OxyPlotWrapper project and select Add New Item.

    9. In the dialog, select User Control. I made the name MyUserControl1.

    Here is the code that I added to these components.

    MyUserControl1.xaml

    <UserControl
        x:Class="OxyPlotWrapper.MyUserControl1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:OxyPlotWrapper"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:oxy="using:OxyPlot.Metro"  
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        
        <Grid>
            <oxy:Plot x:Name="myPlot"/>
        </Grid>
    </UserControl>

    note that you have to add a new namespace in the list.

    MyUserControl.cs

    using System.Collections.Generic;
    using Windows.UI.Xaml.Controls;
    
    using OxyPlot;
    using OxyPlot.Series;
    
    namespace OxyPlotWrapper
    {
        public sealed partial class MyUserControl1 : UserControl
        {
            public MyUserControl1()
            {
                this.InitializeComponent();
            }
    
            public void makePlot(IList<double> array)
            {
                PlotModel model = new PlotModel("TEST", "just a test");
                var series1 = new LineSeries("Series 1") { MarkerType = MarkerType.None};
    
                for (int i = 0; i < array.Count; i+=2)
                {
                    series1.Points.Add(new DataPoint(array[i], array[i+1]));
                }
                model.Series.Add(series1);
                myPlot.Model = model;
            }    
        }   
    }

    This has a simple public method, makePlot, that takes an array of doubles (in pairs x and y) and passes it to the OxyPlot control that is instantiated in the XAML.

    In the C++/XAML project, this plot is added to the XAML like this:

    <Page
        x:Class="TestOxyPlot.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestOxyPlot"
        xmlns:plot="using:OxyPlotWrapper"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <plot:MyUserControl1 x:Name="graph" Width="500" Height="300" />
        </Grid>
    </Page>

    Again, note that you have to add a namespace to the list (using:OxyPlotWrapper).

    Finally, to test this, here is some C++ code that puts some data into the plot.

    #include "pch.h"
    #include "MainPage.xaml.h"
    
    using namespace TestOxyPlot;
    
    using namespace Platform;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Navigation;
    
    MainPage::MainPage()
    {
    	InitializeComponent();
    	Windows::Foundation::Collections::IVector<double>^ data = ref new Platform::Collections::Vector<double>();
    	double y1 = 0.0f;
    	double x1 = 0.0f;
    	for (int i = 0; i < 200; i+=2)
    	{
    		x1 = static_cast<FLOAT>(i);
    		y1 = 100.0f*sin(x1*3.1415f/50.0f);
    		data->Append(x1);
    		data->Append(y1);		
    	}
    	graph->makePlot(data); //Send data to UserControl
    }

    Run the project and you should see a sine wave.  For some unknown reason, the VS designer will complain about the plot but it does build and run just fine for me.

    I don't know if this will will pass certification.

    Ever think about doing your projects in C#?  It is much. much easier.

    ***UPDATE: The solution will not work on an Arm platform.  x86 architecture is required.






    Friday, August 9, 2013 4:08 AM

All replies

  • I'm not familiar with Oxyplot, but from the screenshot and a quick glance at http://oxyplot.codeplex.com/ it looks like OxyPlot is a .Net Portable Class Library (PCL) rather than a Windows Runtime Component. If that is correct it can be called only from .Net, not from C++/Cx.

    You might want to ask on the OxyPlot site to confirm.

    You could create your own Windows Runtime Component in C# which wraps and exposes OxyPlot's PCL.

    --Rob

    Thursday, August 8, 2013 4:31 PM
    Owner
  • How would I go about creating a new .Net PCL project?  I do not find that option in the windows store in visual studio 2012.
    Thursday, August 8, 2013 6:11 PM
  • I was able to cobble something together as a learning challenge for myself.  There may be a better way to do it and, if so, I hope someone provides a better solution.  So here goes....

    You can install OxyPlot in a C# project because it is based on .Net   So my solution is to create a Windows Runtime Component based on C# and including OxyPlot.  The component will consist of a UserControl that you can add to your C++/XAML project.  The C++ code can send data to the UserControl for plotting.

    Here are the steps:

    1. Create a new solution/project based on the C# Windows Runtime Component.  I called mine "OxyPlotWrapper".

    2. Use the Nuget Package Manager Console to install OxyPlot for Metro.

    3. Save the solution.

    4. Load your C++/XAML project into VS

    5. In the Solution Explorer, right click on the Solution and then select Add Existing Project

    6. Browse to your OxyPlotWrapper solution and find the OxyPlotWrapper.csproj and click Open.  It should now show up as a new project in your solution.

    7. In the Solution Explorer, right click on the C++/XAML project and select References then Add New Reference then in Projects Tab find OxyPlotWrapper and click the checkbox then OK.

    8. Now in the Solution Explorer, right click on the OxyPlotWrapper project and select Add New Item.

    9. In the dialog, select User Control. I made the name MyUserControl1.

    Here is the code that I added to these components.

    MyUserControl1.xaml

    <UserControl
        x:Class="OxyPlotWrapper.MyUserControl1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:OxyPlotWrapper"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:oxy="using:OxyPlot.Metro"  
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        
        <Grid>
            <oxy:Plot x:Name="myPlot"/>
        </Grid>
    </UserControl>

    note that you have to add a new namespace in the list.

    MyUserControl.cs

    using System.Collections.Generic;
    using Windows.UI.Xaml.Controls;
    
    using OxyPlot;
    using OxyPlot.Series;
    
    namespace OxyPlotWrapper
    {
        public sealed partial class MyUserControl1 : UserControl
        {
            public MyUserControl1()
            {
                this.InitializeComponent();
            }
    
            public void makePlot(IList<double> array)
            {
                PlotModel model = new PlotModel("TEST", "just a test");
                var series1 = new LineSeries("Series 1") { MarkerType = MarkerType.None};
    
                for (int i = 0; i < array.Count; i+=2)
                {
                    series1.Points.Add(new DataPoint(array[i], array[i+1]));
                }
                model.Series.Add(series1);
                myPlot.Model = model;
            }    
        }   
    }

    This has a simple public method, makePlot, that takes an array of doubles (in pairs x and y) and passes it to the OxyPlot control that is instantiated in the XAML.

    In the C++/XAML project, this plot is added to the XAML like this:

    <Page
        x:Class="TestOxyPlot.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestOxyPlot"
        xmlns:plot="using:OxyPlotWrapper"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <plot:MyUserControl1 x:Name="graph" Width="500" Height="300" />
        </Grid>
    </Page>

    Again, note that you have to add a namespace to the list (using:OxyPlotWrapper).

    Finally, to test this, here is some C++ code that puts some data into the plot.

    #include "pch.h"
    #include "MainPage.xaml.h"
    
    using namespace TestOxyPlot;
    
    using namespace Platform;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Navigation;
    
    MainPage::MainPage()
    {
    	InitializeComponent();
    	Windows::Foundation::Collections::IVector<double>^ data = ref new Platform::Collections::Vector<double>();
    	double y1 = 0.0f;
    	double x1 = 0.0f;
    	for (int i = 0; i < 200; i+=2)
    	{
    		x1 = static_cast<FLOAT>(i);
    		y1 = 100.0f*sin(x1*3.1415f/50.0f);
    		data->Append(x1);
    		data->Append(y1);		
    	}
    	graph->makePlot(data); //Send data to UserControl
    }

    Run the project and you should see a sine wave.  For some unknown reason, the VS designer will complain about the plot but it does build and run just fine for me.

    I don't know if this will will pass certification.

    Ever think about doing your projects in C#?  It is much. much easier.

    ***UPDATE: The solution will not work on an Arm platform.  x86 architecture is required.






    Friday, August 9, 2013 4:08 AM
  • As I said before, I'm a structure engineer.  I went around asking what language I should learn to write windows 8 apps.  Every developer I talked to swore up and down c++ was the best and most supported one.  Who knew they were pulling my leg?

    You are absolutely right.  After I published the current one, my next project will be done in c#.  Are you in the c# forum? 

    One thing that's going to be a hassle is I'll have to re-figure out all the codes like putting the same image in all the xaml pages' background and

    Friday, August 9, 2013 3:26 PM
  • There are certainly advantages for using C++ such as the use of existing libraries (there are many) and performance but you can usually write the bulk of your app in C#/XAML and call C++ WinRT components if you need to do something computationally intensive.

    I monitor the C# forum.  There is much more activity there and usually quick response to queries.

    Conversion will be easier than you think.  No #includes.  No .h files.  Use the '.' instead of '::' and '->' and var instead of auto and 80% of the work is done.  It is a very productive environment.

    Friday, August 9, 2013 3:52 PM