Changing and setting the Legend (LineGraph) Future of DynamicDataDisplay - c#

I'm using this great library https://d3future.codeplex.com/ to plot some 2D graphs.
In the old D3 I used to set the legend this way:
graf = plotter.AddLineGraph(new CompositeDataSource(xSrc, plot),
new Pen(brush, 4),
new PenDescription("myText" ));
But I have no idea how to obtain the same in future D3. Could someone make me see the light?
Exploring the source code I find this but can't understand how to access and change the default string "LineGraph":
public class LineGraph : PointsGraphBase
{
static LineGraph()
{
Type thisType = typeof(LineGraph);
Legend.DescriptionProperty.OverrideMetadata(thisType, new FrameworkPropertyMetadata("LineGraph"));
Legend.LegendItemsBuilderProperty.OverrideMetadata(thisType, new FrameworkPropertyMetadata(new LegendItemsBuilder(DefaultLegendItemsBuilder)));
}
//more stuff
}

v0.4.0 uses the following syntax:
// For access to the Legend class
using Microsoft.Research.DynamicDataDisplay.Charts;
... snip ...
LineGraph lineGraph = new LineGraph(dataSource);
lineGraph.LinePen = new Pen(Brushed.Green, 1.0);
Legend.SetDescription(lineGraph, "The line label");
plotter.Children.Add(lineGraph);
... snip ...
v0.3.0 used the following syntax:
plotter.AddLineGraph(dataSource, pen, marker, new PenDescription("The line label"));

When you add line graph to the plotter (AddLineGraph(...)), one of the parameters is description string.

WGW is Spot On! Thumbs Up from me.
I found that doing it a slightly different way was easier to understand:
<Page
...
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
... >
...
<Grid Name="GridOne" Grid.Column="0" Grid.Row="0" Margin="13" />
</Page>
And the Code Behind:
using Microsoft.Research.DynamicDataDisplay.Charts;
...
ChartPlotter PlotterOne = new ChartPlotter();
// Add a Graph to One:
GridOne.Children.Add(PlotterOne);
LineGraph line = new LineGraph();
line.ProvideVisiblePoints = true;
line.Stroke = Brushes.Blue;
line.StrokeThickness = 1;
line.DataSource = GetDayDataSource();
Legend.SetDescription(line, "Today's Activity");
PlotterOne.Children.Add(line);
Hope this helps.

Related

How to draw a tab control border

I have a custom tab control but I wish to remove the Left, bottom and right big border like the picture bellow, I dont know how these variable work and searching didnt give me anything related to it. Sorry i just start to learn coding.
Here is the code, i tried to play around with it but it gave me weird borders all the time. Can you help me? Or please tell me how does it work. Thank you!
public virtual void DrawBorder(Graphics g, Rectangle borderBounds)
{
if (Parent.SelectedIndex == -1)
{
using (Pen pen = new Pen(BorderColor))
{
g.DrawRectangleFixed(pen, borderBounds);
}
return;
}
var tabBounds = Parent.GetTabBounds(Parent.SelectedTab);
Point[] pt = new Point[8];
if ((Parent.TabLocation & TabLocation.Top) != TabLocation.None)
{
pt[0] = borderBounds.GetBottomLeft().GetOffset(0, -1);
pt[1] = borderBounds.GetBottomRight().GetOffset(-1, -1);
pt[2] = borderBounds.GetTopRight().GetOffset(-1, 0);
pt[3] = tabBounds.GetBottomRight().GetOffset(-1, -1);
pt[4] = tabBounds.GetTopRight().GetOffset(-1, 0);
pt[5] = tabBounds.GetTopLeft();
pt[6] = tabBounds.GetBottomLeft().GetOffset(0, -1);
pt[7] = borderBounds.GetTopLeft();
}
else if ((Parent.TabLocation & TabLocation.Bottom) != TabLocation.None)
{
pt[0] = borderBounds.GetBottomLeft().GetOffset(0, -1);
pt[1] = tabBounds.GetTopLeft();
pt[2] = tabBounds.GetBottomLeft().GetOffset(0, -1);
pt[3] = tabBounds.GetBottomRight().GetOffset(-1, -1);
pt[4] = tabBounds.GetTopRight().GetOffset(-1, 0);
pt[5] = borderBounds.GetBottomRight().GetOffset(-1, -1);
pt[6] = borderBounds.GetTopRight().GetOffset(-1, 0);
pt[7] = borderBounds.GetTopLeft();
}
using (Pen pen = new Pen(BorderColor))
{
g.DrawPolygon(pen, pt);
}
}
I agree with others suggesting having a reproducible example makes helping easier. So please don't mind if I was doing the wrong guesses ...
First, what is the point to leave away the outside borders of your tab control? One of the UI purpose of a tab control is to group some and optically separate controls them from the rest of those in your UI.
Second, if you still like to do that, why are you (probably) creating your own TabControl subclass and take care of custom drawing at all? You can archive this in the XAML code directly by using the TabControl BorderThickness property:
<TabControl BorderThickness="0">
<TabItem Header="Tab1">
<TextBox Text="First Textbox"/>
</TabItem>
<TabItem Header="Tab2">
<TextBox Text="Second Textbox"/>
</TabItem>
</TabControl>
Finally, if you like to style any control rather than adding / changing its functionality, think about using XAML styling instead of creating a custom control.

C# Equivalent code for xaml phrases

I need too add some control unit such as Grid, Checkbox ,Textblock and ... dynamically in my C# Code.
Assume XAML node like:
<CheckBox Content="CheckBox" Height="24" Click="CheckBoxes_Click"/>
Its C# equivalent is
AddNewCheckBox()
{
CheckBox NewCheckBox = new CheckBox ();
NewCheckBox.Content = "CheckBox1";
NewCheckBox.Height = 24;
NewCheckBox.Click += CheckBoxes_Click;
}
But there are many XAML assignment which it is hard to understand their C# equivalent.
As an example what should I write in my c# to create a CheckBox like this?
<CheckBox Content="CheckBox" Margin="68,41,0,0" Background="Black"
Height="Auto" Click="CheckBoxes_Click"/>
Is there any way to understand how XAML parser maps phrases to C# code?
Is there any way to understand how XAML parser maps phrases to C# code?
Looking at this example:
<CheckBox Content="CheckBox"
Margin="68,41,0,0"
Background="Black"
Height="Auto"
Click="CheckBoxes_Click"/>
If we want to understand how the XAML parser knows how to set more complicated properties (ones that cannot simply use the TryParse() methods of the types) we need to look at the types of the properties.
If you look at the Margin property for example it is of type Thickness and if you look at that type you will find this attribute:
[TypeConverter(typeof(ThicknessConverter))]
If you look at that type (in PresentationFramework.dll) with for example dotPeek you will find ConvertFrom(...) and ConvertTo(...) methods that take care of the conversion. The internal method FromString(...) contains the relevant parts for this example.
To create checkbox like that you should write it like this:
AddNewCheckBox()
{
CheckBox NewCheckBox = new CheckBox ();
NewCheckBox.Content = "CheckBox1";
NewCheckBox.Height = 24;
NewCheckBox.Click += NewCheckBox_Click;
NewCheckBox.Margin = new Thickness(64, 41, 0, 0);
NewCheckBox.Background = new SolidColorBrush(Color.Black);
//or like this: NewCheckBox.Background = Brushes.Black;
}
what should I write in my c# to create a check box like this?
<CheckBox Content="CheckBox"
Margin="68,41,0,0"
Background="Black"
Height="Auto"
Click="CheckBoxes_Click"/>
The above equates to
var checkBox = new CheckBox () {
Content = "CheckBox",
Margin = new Thickness(64, 41, 0, 0),
Background = Brushes.Black,
Height = Double.NaN
};
checkBox.Click += CheckBoxes_Click
As an example what should I write in my c# to create a CheckBox like this?
The same more or less. Each attribute in XAML maps to a property in C#. So the equivalent would be:
CheckBox checkBox = new CheckBox();
checkBox.Content = "CheckBox";
checkBox.Margin = new Thickness(68,41,0,0);
checkBox.Background = Brushes.Black;
checkBox.Click += CheckBoxes_Click;
The type of the Background property is Brush. And the type of the Margin property is Thickness. You can confirm this by looking at the documentation on MSDN.
The XAML processor is able to translate the string "Black" to a Brush and the value "68,41,0,0" to a Thickness for you. The C# compiler is not. Apart from this, you are setting the exact same properties of the exact same class.

OxyPlot, Points not in LineSeries

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

Unable to bind whole Chart to Frontend

I am looking for a way to bind a whole Chart in my xaml. Not only one Series, but the whole Chart. This is due to my need to add multiple Series dynamically to the Chart.
XAML:
<chart:Chart DataContext="{Binding Path=FocusEnergyChart, UpdateSourceTrigger=PropertyChanged}"/>
C#:
public void DrawChart()
{
myChart = new Chart();
LinearAxis xAxis = new LinearAxis();
xAxis.Orientation = AxisOrientation.X;
xAxis.Title = "Energy";
LinearAxis yAxis = new LinearAxis();
yAxis.Orientation = AxisOrientation.Y;
yAxis.Title = "Focus";
myChart.Axes.Add(xAxis);
myChart.Axes.Add(yAxis);
myChart.Title = "Focus Energy - Chart";
foreach( string aKey in myGraphData.Keys)
{
BubbleSeries aSeries = new BubbleSeries();
aSeries.Title = aKey;
aSeries.ItemsSource = myGraphData[aKey];
aSeries.DependentValuePath = "Focus";
aSeries.IndependentValuePath = "Energy";
aSeries.SizeValuePath = "Size";
aSeries.SetResourceReference(Series.BackgroundProperty, "Background");
aSeries.SetResourceReference(BubbleSeries.LegendItemStyleProperty, "CustomLegendItemStyle");
aSeries.SetResourceReference(BubbleSeries.DataPointStyleProperty, "BubbleToolTipTemplate");
myChart.Series.Add(aSeries);
}
base.OnPropertyChanged("FocusEnergyChart");
}
public Chart FocusEnergyChart
{
get { return myChart; }
}
When i try to run this code it just shows me an empty ChartArea.
I hope someone can help me!
Thanks!
All you do here is add another chart as the DataContext of your chart declared from XAML.
You can use a ContentControl and bind it's content to your chart created from code-behind:
<ContentControl Content="{Binding Path=FocusEnergyChart}" />

How to assign a dynamic resource style in code?

I want to produce in code the equivalent of this in XAML:
<TextBlock
Text="Title:"
Width="{Binding FormLabelColumnWidth}"
Style="{DynamicResource FormLabelStyle}"/>
I can do the text and the width, but how do I assign the dynamic resource to the style:
TextBlock tb = new TextBlock();
tb.Text = "Title:";
tb.Width = FormLabelColumnWidth;
tb.Style = ???
You should use FrameworkElement.SetResourceReference if you want true DynamicResource behaviour - ie updating of the target element when the resource changes.
tb.SetResourceReference(Control.StyleProperty, "FormLabelStyle")
You can try:
tb.Style = (Style)FindResource("FormLabelStyle");
Enjoy!
The original question was how to make it Dynamic, which means if the resource changes the control will update. The best answer above used SetResourceReference. For the Xamarin framework this is not available but SetDynamicResource is and it does exactly what the original poster was asking. Simple example
Label title = new Label();
title.Text = "Title";
title.SetDynamicResource(Label.TextColorProperty, "textColor");
title.SetDynamicResource(Label.BackgroundColorProperty, "backgroundColor");
Now calling:
App.Current.Resources["textColor"] = Color.AliceBlue;
App.Current.Resources["backgroundColor"] = Color.BlueViolet;
Causes the properties to change for all controls using the resource this way. This should work for any property.
This should work:
tb.SetValue(Control.StyleProperty, "FormLabelStyle");
Application.Current.Resources.TryGetValue("ResourceKey", out var value)

Categories

Resources