I have a hard time getting OxyPlot to display my data in my standalone WPF application (I use caliburn micro, and follow the MVVM pattern).
So in my Xaml I have the following:
<UserControl ...
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf">
and later
<oxy:Plot Title="Winnings of Selected Player" Model="{Binding Graph1}"/>
In my ViewModel, I seem to have the choice to either include using OxyPlot; or using OxyPlot.Wpf;. If I do the former, I can define my PlotModel as follows:
private PlotModel _graph1;
public PlotModel Graph1 {
get { return _graph1;}
set {
_graph1 = value;
Graph1.RefreshPlot(true);
}
}
public MyViewModel() {
Graph1 = new PlotModel();
var FirstSeries = new LineSeries();
FirstSeries.Points.Add(new DataPoint(1,2));
FirstSeries.Points.Add(new DataPoint(1,2));
}
but my view does not display anything (in fact, I don't even see an 'empty graph', or the title in the view). I have tried scattering the RefreshPlot command all over the place, too ...
So then, I figure to try using OxyPlot.Wpf; instead. Then, however, I cannot add Points to my LineSeries - here's a screenshot of my IntelliSense ...
!(http://imageshack.com/a/img30/2441/cvqy.png)
So how do I populate data into my LineSeries using OxyPlot.Wpf? By the way, I still don't see an empty graph, even when I compile without adding points to the LineSeries. All examples I have looked at do this, or they write code in tha .xaml.cs code-behind file which I don't want to do.
EDIT: As dellywheel mentiones, I forgot to add the LineSeries to my PlotModel above when asking the question, so the constructor above should contain the line
Graph1.Series.Add(FirstSeries);
But that was just in typing the question, ofc not the real problem ...
You havent added the LineSeries to the Graph and the Graph is Graph1 not Graph
Try
public MyViewModel(){
Graph1 = new PlotModel();
var firstSeries = new LineSeries();
firstSeries.Points.Add(new DataPoint(1, 2));
firstSeries.Points.Add(new DataPoint(1, 2));
Graph1.Series.Add(firstSeries);
}
Hope that helps
Related
I am struggling in very beginning with WPF and LiveCharts.
I am trying to implement the Starting Example (https://lvcharts.net/App/examples/v1/Wpf/Components) but couldn't understand how it works (or better to say not working for me) and there to to place the snippet into a WPF project.
With XAML it is ok, I just put the example row into the Grid of MainWindow.xaml and while debugging it shows the element
<lvc:CartesianChart Series="{Binding SeriesCollection}" />
But then I did not get into C# part
SeriesCollection = new SeriesCollection
{
new LineSeries
{
Values = new ChartValues<double> { 3, 5, 7, 4 }
},
new ColumnSeries
{
Values = new ChartValues<decimal> { 5, 6, 2, 7 }
}
};
When I add it to public partial class MainWindow it is interpreted wrong.
And I do not understand what happen in the first row:
SeriesCollection = new SeriesCollection
As I understand, we are to create an object with a constructor which add LineSeries and ColumnSeries values to an object of class SeriesCollection.
So it shold be like
SeriesCollection mySeries = new SeriesCollection()
This one is compiling properly, but anyway I couldn't get a binding to mySeries object:
No DataContext found for binding 'mySeries' for my "updated" program
No DataContext found for binding 'SeriesCollection' for initital example
It appears the binding requires a get/set e.g.
public SeriesCollection SeriesCollection { get; set; }
You also require the DataContext property set in your constructor:
DataContext = this;
Otherwise the binding fails silently at runtime.
It appears the getting started guide is broken at https://lvcharts.net/App/examples/v1/wpf/Components. I had to use the Wayback Machine to find a working copy of the getting started guide: https://web.archive.org/web/20190717052904/https://lvcharts.net/App/examples/v1/wpf/Basics
I'm new at using Fluent layout for a Xamarin.iOS project and I now stumbled on a problem that I don't know how to solve.
The situation is like this:
I have a scrollview as the mainView and some texts inside that, and I now want to add another view (let's call it "subView") containing other texts.
Why I want the "subView" is because I have a "Hide/Show" button that are suppose to Hide or Show the "subView".
Where'm I suppose to add the constraints for positioning the stuff inside "subView"? Inside subView.AddConstraints(), or in mainView.AddConstraints?
I don't know how to do this, can somebody please help me?
Example of what im doing
Try to use this code:
CGRect rect = new CGRect(0, UIApplication.SharedApplication.StatusBarFrame.Height, UIScreen.MainScreen.ApplicationFrame.Width , UIScreen.MainScreen.ApplicationFrame.Height);
UIScrollView Mainscrollview = new UIScrollView(rect) { BackgroundColor = UIColor.Gray };
View.AddSubview(Mainscrollview);
this.View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
var someLablel = new UILabel();
var button = new UIButton { BackgroundColor = UIColor.Gray };
var blueView = new UIView { BackgroundColor = UIColor.Blue };
Mainscrollview.AddSubviews( someLablel,button, blueView);
Mainscrollview.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
Mainscrollview.AddConstraints(
someLablel.AtTopOf(Mainscrollview, 50),
someLablel.AtLeftOf(Mainscrollview, 10),
someLablel.AtRightOf(Mainscrollview, 10),
someLablel.Height().EqualTo(50),
button.AtBottomOf(someLablel, 10),
button.WithSameLeft(someLablel),
button.WithSameRight(someLablel),
button.WithSameHeight(button),
blueView.AtBottomOf(button, 10),
blueView.WithSameLeft(someLablel),
blueView.WithSameRight(someLablel),
blueView.AtBottomOf(Mainscrollview, 10)
);
//*do as above*
//blueView.AddSubviews(SubViewLabel1, Another , more);
//blueView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
//blueView.AddConstraints( );
PS:
As what i said above, FluentLayout is used to describe the relationship between parenet view and subview or subview and subview (with the same parent view). We can't relate subview to it's super super view (e,g ,subviewLabel and Mainscrollvew in the pic). And What's the most important is the Constraints we add must be sufficient, which means the view must get its position and size with those Constraints.
Where'm I suppose to add the constraints for positioning the stuff inside "subView"? Inside subView.AddConstraints(), or in mainView.AddConstraints?
Views are assigned the constraints which lay out their direct subviews, so the controls inside subView should be laid out with subView.AddConstraints(). If subView is a subview of mainView, then it should be laid out with mainView.AddConstraints().
EDIT: An example:
mainView.Add(subView);
subView.Add(someOtherView);
var myPadding = 12f;
mainView.AddConstraints(new FluentLayout[]
{
subView.AtTopOf(mainView, myPadding),
subView.AtLeftOf(mainView, myPadding),
subView.AtRightOf(mainView, myPadding),
subView.AtBottomOf(mainView, myPadding)
});
subView.AddConstraints(new FluentLayout[]
{
someOtherView.AtTopOf(subView, myPadding),
someOtherView.AtLeftOf(subView, myPadding),
someOtherView.AtRightOf(subView, myPadding),
someOtherView.AtBottomOf(subView, myPadding)
});
Hiding and showing views is a separate issue - you would need to destroy and recreate separate constraints when an action is taken that shows or hides subView, or use MvvmCross to bind certain constraints to ViewModel properties, which you can find instructions on here.
I'm trying to use OxyPlot in a scenario where I'm setting up the chart type, and then adding 1 or more series to it programmatically. To this end:
in the XAML view, I simply add a PlotView control.
in the code, my class has a PlotModel property (notifying changes), and an AddSeries method. Whenever this is invoked, I setup the plot model if not yet configured (I create a new PlotModel object and add a LinearAxis), create a random data LineSeries, and add it to the Series collection of the plot model. Finally, I invoke InvalidatePlot(true) on it to force it to redraw.
Yet, nothing is displayed when I execute this code, which raises no error.
I googled around a bit but the only code samples I found refer to the typical scenario where a XAML view binds to a bound datasource; but here I'm recreating the PlotModel each time, according to the chart type and series count. You can find a dummy repro solution here: http://1drv.ms/1R8EFBc . Just compile and run, and click Add series. Could anyone suggest a solution?
The bound property PlotModel is never updated due to:
private void SetupPieChart()
{
if (_plot == null) _plot = new PlotModel();
else _plot.Axes.Clear();
}
Change to following and it should work:
private void SetupPieChart()
{
if (PlotModel == null) PlotModel = new PlotModel();
else PlotModel.Axes.Clear();
}
Since :
private PlotModel _plot;
public PlotModel PlotModel
{
get { return _plot; }
set
{
_plot = value;
OnPropertyChanged(); // <=== update here
}
}
Basically, I want to make bunch of Shapes and make them animated. So I came up with following custom class:
public class FunkyShape : DependencyObject
{
public double Animator
{
get { return (double)GetValue(AnimatorProperty); }
set { SetValue(AnimatorProperty, value); }
}
public static readonly DependencyProperty AnimatorProperty =
DependencyProperty.Register("Animator", typeof(double), typeof(FunkyShape),
new PropertyMetadata(0, new PropertyChangedCallback(Animator_Changed)));
private static void Animator_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
double delta = (double)e.NewValue - (double)e.OldValue;
((FunkyShape)d).ProcessDelta((double)e.NewValue, delta);
}
private void ProcessDelta(double val, double delta)
{
Holder.Width = val;
Holder.Height = val;
// Keep shape centered
HolderPosition.X = delta / 2;
HolderPosition.Y = delta / 2;
}
private Shape Holder;
public TranslateTransform HolderPosition
{
get { return (TranslateTransform)Holder.RenderTransform; }
}
public FunkyShape(Canvas playground, Shape shapeToInit)
{
Holder = shapeToInit;
Holder.Width = 10;
Holder.Height = 10;
Holder.Fill = new SolidColorBrush(Colors.Blue);
Holder.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center;
Holder.RenderTransform = new TranslateTransform()
{
X = 500,
Y = 500
};
Holder.RenderTransformOrigin = new Point(0.5, 0.5);
// init done
playground.Children.Add(Holder);
Animate();
}
public void Animate()
{
DoubleAnimation g1 = GrowAnimation();
Storyboard sb = new Storyboard();
Storyboard.SetTarget(g1, this);
// CAN'T FIND ANIMATOR PROPERTY
Storyboard.SetTargetProperty(g1, "Animator");
sb.Children.Add(g1);
sb.Begin(); // THROWS EXCEPTION
}
private static DoubleAnimation GrowAnimation()
{
DoubleAnimation growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(3000);
growAnimation.From = 0;
growAnimation.To = 100;
growAnimation.AutoReverse = true;
growAnimation.EnableDependentAnimation = true;
growAnimation.RepeatBehavior = new RepeatBehavior(5);
return growAnimation;
}
}
However, when I try making an instance of the class and adding it to the canvas, I get Exception - Storyboard.Being() throws it and tells me that it can't find Animator property.
So - what am I doing wrong?
EDIT: After 3 code changes - it is still not working; I get "Cannot resolve TargetProperty Animator on specified object" error. So if somebody knows the answer - please help out by modifying the code. Thanks!
EDIT: OK, after 24 hours of banging head against the wall there is some progress - if I add shape through XAML it animates, but if I add it through code behind (Canvas.Children.Add), it doesn't work. Let me see if I can figure out why.
OK,
I've found the workaround for what is obviously a bug within the framework (although I'm sure some MS employee will post response and say it's a feature/it-is-by-design). Several things need to be done:
Add default/parameter-less constructor
Change base class of FunkyShape to UserControl.
Open up XAML view of the Page class where you want to add shapes
Add one instance of FunkyShape as a child within the Canvas XAML (<tm:FunkyShape /> for example). IT WON'T WORK WITHOUT THIS.
Make an instance of FunkyShape in code-behind, add it to canvas, start animation and enjoy seeing it works
Switch to less buggy technology.
In Windows 8 you cannot animate custom properties without also setting the enabledependentanimation property to true. This is because non-deterministic animations are disabled by default.
Reference: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx
Yes, you must define this property as a dependency property, not just a regular CLR property. This involves quite a bit of simple boiler plate code. See thus blog post for a complete example:
http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx
OK, I had this problem too, but I didn't want to include a public parameterless constructor in my class, so I found another way.
Basically, the issue is that WinRT is a native platform, and it can't do reflection on .NET code. That's why the build process for WinRT apps generates metadata about the types used in XAML (you can find the relevant code in obj/(Debug|Release)/XamlTypeInfo.g.cs).
If a type is never used in XAML, no metadata about this type is generated, which means (among other things) that you can't animate the properties of the type.
If you're writing a class library, you can just include a XAML resource dictionary and declare a dummy instance of the type; it will cause metadata to be generated. However, it requires that the type has a public parameterless constructor, which might not be desirable.
So there is another solution: provide the metadata yourself. There are a several interfaces to implement, and they have many members, so it can be quite tedious to do manually. Fortunately, you don't have to! Here's what you can do:
add a public parameterless constructor to the class (temporarily)
create a XAML ResourceDictionary and declare an instance of the class in it (as described above)
copy the XamlTypeInfo.g.cs file into your project (I renamed it to XamlTypeInfo.cs)
replace the call to the constructor with throw new NotImplementedException()
delete the ResourceDictionary file
remove the public parameterless constructor
And you're done, the animation now works properly.
The process is still quite tedious, so it would be nice to have a tool to do the work for us...
EDIT: much easier solution: apply the [Bindable] attribute to the class. It makes the metadata generator take the type into account even if it's not used in XAML. (ignore the fact that the doc says it's for C++ types; it works just fine on C# classes as well)
I have the following code:
[OnTap ("Account")]
[Alignment (UITextAlignment.Center)]
[Entry ("Create ScanDo! Account")]
public string Login;
And I'd like to set the Cell background color dynamically, based on the contents of another field and then after the button is clicked. Could anyone point me in a direction with some samples?
Thanks,
Rick
The answer I came up with:
btnLogin = new StyledStringElement("", delegate {Account();})
To define the object, add it to the RootElement, then:
btnLogin.BackgroundColor = UIColor.Green;
To set the color! This method let me set color, font, size and caption.
Great work Miguel, Thanks!
As you're adding the button to the root collection you can set the colour. Just as you set the elements of a section.
Root = new RootElement("First Section") {
new Section ("Test"){
new StyledStringElement("Login", delegate { Account(); })
{
BackgroundColor = UIColor.Green
}
}
}
I don't like to keep pimping my projects but in this case it is the best option for you.
Check out https://github.com/RobertKozak/MonoMobile.MVVM
My project started out as adding Databinding support to MonoTouch.Dialog but has grown into a much bigger framework that is much easier to use than MonoTouch.Dialog.
Using MonoMobile.MVVM the code to do what you want looks like this:
public class ButtonView : View, INotifyPropertyChanged
{
private UIColor ButtonColor = UIColor.Red;
[Button]
[Bind("ButtonColor", "BackgroundColor")]
public void Test()
{
ButtonColor = UIColor.Green;
PropertyChanged(this, new PropertyChangedEventArgs("ButtonColor"));
}
public event PropertyChangedEventHandler PropertyChanged = (s,e)=>{};
}
There are better ways to accomplish this using a proper ViewModel but this will work as listed (I tested it before I typed it in here.)
MonoMobile.MVVM is still in beta but there is enough there to get you going. It should be in full release status in the next couple of weeks after I finish up implementing INotifyCollectionChanged and adding a few more bindings for various Element properties.