Change Lineseries thickness in WPFToolkit.Chart C# - wpf

I'm trying change the line thickness in a serie dinamically created, I need turn the line more thick.
Below, follow the code to bind the created serie on chart component. It works fine, but I tryed adapt this in this code and I had no sucess.
Please help, thanks.
Style style = new Style(typeof(LineDataPoint));
style.Setters.Add(new Setter(LineDataPoint.OpacityProperty, (double)(0.0)));
style.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, dadosSerie.ColorSerie));
LineSeries lineSerie = new LineSeries()
{
Title = dadosSerie.SerieTitle,
IndependentValueBinding = new Binding("Key"),
DependentValueBinding = new Binding("Value"),
DependentRangeAxis = dadosSerie.EixoY,
DataPointStyle = style,
ItemsSource = dadosSerie.DataSerie,
};
chtGraficos.Series.Add(lineSerie);

Have you tried adding a Style for the serie's Polyline instead?
It seams the style for the LineDataPoint is actually for every point on the serie.
Here is a working sample of a chart fully created on code-behind. You just have to create a window named MainWindow and add a reference on the project to System.Windows.Controls.DataVisualization.Toolkit:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var valueList = new Dictionary<string, int>();
valueList.Add("Developer", 60);
valueList.Add("Misc", 20);
valueList.Add("Project Manager", 40);
var style = new Style(typeof(Polyline));
style.Setters.Add(new Setter(Polyline.StrokeThicknessProperty, 10d));
var series = new LineSeries
{
PolylineStyle = style,
ItemsSource = valueList,
DependentValuePath = "Value",
IndependentValuePath = "Key",
};
var lineChart = new Chart { Height = 254 };
lineChart.Series.Add(series);
var mainGrid = new Grid();
mainGrid.Children.Add(lineChart);
this.Content = mainGrid;
}
}

Related

Combobox binding not working when window is in grid container

I try to bind a list in ComboBox with this code :
var template = new DataTemplate();
var comboBoxFactory = new FrameworkElementFactory(typeof(ComboBox));
template.VisualTree = comboBoxFactory;
Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("DataContext");
comboBoxFactory.SetBinding(ComboBox.ItemsSourceProperty, b);
comboBoxFactory.SetBinding(ComboBox.SelectedItemProperty, new Binding("ClassRoom"));
It's working when I launch the window simply, like this :
winListOrgane ee = new winListOrgane();
ee.Show();
But when I try to put this window in a grid container, it's not working :
_currentWindow = (ModelPage)Activator.CreateInstance(pPage.GetType());
_currentWindow.SetParam(genParam);
_currentWindow.InitPage();
object content = _currentWindow.Content;
_currentWindow.Content = null;
_containerPage.Children.Add((UIElement)content);
What can I do to fix this problem?
Thanks
Best regards,
Frederic
It looks like it is your RelativeSource on the Binding. Since you are binding to a specific Window class - in this case it looks like GetType() will return typeof(winListOrgane). If you change that to typeof(Window), it should work:
b.RelativeSource =
new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1);

ItemsControl children return NAN when asking for Canvas.GetLeft

I have a very simple WPF application that renders simple shapes in a canvas:
The blue squares are ItemsControl and the red circles are Controls
The following step in my application is adding connection lines between the shapes. The shaphes will be moved and I want the connections to be automatically moved. I readed about how to do it adding connection bindings.
All worked fine with canvas direct children (container), but if I want to connect the nodes, it does not work. It seems that if I don't call Canvas.SetLeft() and Canvas.SetTop() explicitily, then Canvas.GetLeft() and Canvas.GetTop() return NAN.
How should I proceed?
Should I implement a mechanism to get all objects placed in my canvas, so I always can calculate Canvas.GetLeft() over all of them?
Should I proceed in another way?
Source code and screenshot
This is the source code of the example. You can find here the complete example:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Container container1 = new Container() { Width = 100, Height = 100 };
Node node1 = new Node() { Width = 50, Height = 50 };
container1.Items.Add(node1);
Container container2 = new Container() { Width = 100, Height = 100 };
Node node2 = new Node() { Width = 50, Height = 50 };
container2.Items.Add(node2);
Canvas.SetLeft(container2, 200);
myCanvas.Children.Add(container1);
myCanvas.Children.Add(container2);
}
}
class Container : ItemsControl
{
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(
Brushes.Blue, null, new Rect(0, 0, this.Width, this.Height));
}
}
class Node : Control
{
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawEllipse(
Brushes.Red, null,
new Point(Width / 2, Height / 2), Width / 2, Height / 2);
}
}
This is how I implemented the connections between the shapes:
public Shape AddConnection(UIElement source, UIElement target)
{
Connector conn = new Connector();
conn.SetBinding(Connector.StartPointProperty,
CreateConnectorBinding(source));
conn.SetBinding(Connector.EndPointProperty,
CreateConnectorBinding(target));
return conn;
}
private MultiBinding CreateConnectorBinding(UIElement connectable)
{
// Create a multibinding collection and assign an appropriate converter to it
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = new ConnectorBindingConverter();
// Create binging #1 to IConnectable to handle Left
Binding binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(Canvas.LeftProperty);
multiBinding.Bindings.Add(binding);
// Create binging #2 to IConnectable to handle Top
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(Canvas.TopProperty);
multiBinding.Bindings.Add(binding);
// Create binging #3 to IConnectable to handle ActualWidth
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(FrameworkElement.ActualWidthProperty);
multiBinding.Bindings.Add(binding);
// Create binging #4 to IConnectable to handle ActualHeight
binding = new Binding();
binding.Source = connectable;
binding.Path = new PropertyPath(FrameworkElement.ActualHeightProperty);
multiBinding.Bindings.Add(binding);
return multiBinding;
}
The Connector object is very simple. It has a LineGeometry and exposes two DependencyProperties to calculate the start point and the end point.
public static readonly DependencyProperty StartPointProperty =
DependencyProperty.Register(
"StartPoint",
typeof(Point),
typeof(Connector),
new FrameworkPropertyMetadata(
new Point(0, 0),
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty EndPointProperty =
DependencyProperty.Register(
"EndPoint",
typeof(Point),
typeof(Connector),
new FrameworkPropertyMetadata(
new Point(0, 0),
FrameworkPropertyMetadataOptions.AffectsMeasure));
Everything is so wrong I can't really answer the question without fixing things.
Your nodes and containers shouldn't be controls that use OnRender. There's a lot of expectations in WPF, and one expectation is that you use their controls. If you dig into Microsoft code, they have a lot of things hard-coded for their classes.
You should have data objects for Node and Container that have Connections. Container should have a list of children Nodes.
You'll use a DataTemplate or Style to actually implement the UI. That's where you do your bindings, but don't use a multibinding. Just bind to individual values themselves. If you need to evaluate, then you create ViewModel objects that perform these calculations for you. You don't do your construction code in converters.
Because you're using bindings to connect things and your "connectable" doesn't describe whether it's a node or container or both, I'm going to assume it can be both.
For example:
public interface IConnection
{
IConnectable A { get; set; }
IConnectable B { get; set; }
}
public class Connection : IConnection, Line
{
DependencyProperty AProperty = ...;
DependencyProperty BProperty = ...;
}
public class Node : IConnectable
{
DependencyProperty ConnectionProperty = ...;
}
public class Container : IConnectable
{
DependencyProperty ConnectionProperty = ...;
ObservableCollection<IConnectable> Children = ...;
}
public class ContainerView : IConnectable
{
DependencyProperty ConnectionPointProperty = ...;
DependencyProperty ConnectionProperty = ...;
void OnSizeChanged(...)
{
RecalcConnectionPoint();
}
void OnConnectionPointOtherChanged()
{
RecalcConnectionPoint();
}
void RecalcConnectionPoint()
{
if (Connection.A == this)
{
if (Connection.B.ConnectionPoint.Left < this.Left)
{
ConnectionPoint = new Point(Left, Top + Height/2);
}
else
{
ConnectionPoint = new Point(Right, Top + Height/2);
}
}
}
}
Then you would bind the properties that match up from your Model classes to your ViewModel classes. Then manipulating the data in your Model classes would update your View.
Your Styles for your Container and Nodes would decide how to draw them, so say one day you decide a Node should look like a Rectangle instead... You change a style and don't have to dig through OnRender code.
This is how you design WPF programs.
Other benefits.
If you were to put a "Connection UI Object" somewhere on the Container, you'd bind to it's point instead. You could use a Grid to align the ConnectionPointView, and then the ConnectionPoint would be updated automatically.

Print WPF grid is cropped

I found function to print content of Wpf grid but the print is cropped.
Can anybody know why?
the function:
private void PrintTest()
{
FlowDocument document;
Window window;
CreateWindowToPrint(out document, out window);
PrintDialog printDialog = new PrintDialog();
window.Show();
IDocumentPaginatorSource dps = document;
if (printDialog.ShowDialog() == true)
{
printDialog.PrintDocument(dps.DocumentPaginator, "test");
}
}
and:
private void CreateWindowToPrint(out FlowDocument document, out
Window window)
{
document = new FlowDocument { };
var test = new PrintedTest() { DataContext = this.DataContext };
document.Blocks.Add(new BlockUIContainer { Child = test });
window = new Window {Content = document, Visibility = System.Windows.Visibility.Hidden };
}
The UserControl PrintedTest contains my grid.
I don't really have much experience with printing in WPF but I thought I would give it a try.
I could reproduce your problem, and I could not solve it so far.
But In my research I have found an alternative, which is more simple to print the Grid:
var printDialog = new PrintDialog();
var result = printDialog.ShowDialog();
if (result.HasValue && result.Value)
{
var testControl = new PrintedTest() { DataContext = this.DataContext };
printDialog.PrintVisual(testControl, "My WPF printing a DataGrid");
}
Instead of sending the PrintTest you could actually just send directly the grid.

Set panoramaItem Orientation via code in WP7

I have added the images dynamtically from a url to panorama item. I need the width to be 800 which the image should be in the next item space also. For that in my previous application I have set the orientation to horizontal in Xaml. But no i need to set in code but i cant is there any way to do that.
private void AddItem(string uri, string header)
{
var panoramaItem = new PanoramaItem();
panoramaItem.Width = 800;
panoramaItem.Height = 550;
panoramaItem.Header = "";
var grid = new Grid();
var image = new Image();
image.Source = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute));
panoramaItem.Content = image;
pan.Items.Add(panoramaItem);
}
PanoramaItem has an Orientation property for handling scrolling direction. It takes value of System.Windows.Controls.Orientation enum in System.Windows assembly. Your code should looks like:
using System.Windows.Controls;
And orientation assigment:
panoramaItem.Orientation = Orientation.Horizontal;

WPF Binding a Dynamically Added Control

I am adding a to the "Company" RibbonApplicationMenuItem in my RibbonWindow with the following code:
var reset = DataContext as ICompanies;
if (reset != null)
{
// ToDo: Create interface to populate the mymenutems
var mymenuitems = new List<string>();
foreach (var item in mymenuitems)
{
var newbutton = new Button { Margin = new Thickness(2), Content = item };
MenuItem_Company.Items.Add(newbutton);
}
}
My XAML looks like this:
<ribbon:RibbonApplicationMenu ToolTipTitle="Application Menu">
<ribbon:RibbonApplicationMenuItem
Header="Company"
x:Name="MenuItem_Company"
ImageSource="Images\LargeIcon.png">
</ribbon:RibbonApplicationMenuItem>
</ribbon:RibbonApplicationMenu>
How do I bind my new button in code when I add it to the MenuItem_Company? I need it to bind to a property in my datacontext.
Thanks,
Eroc
var newbutton = new Button { Margin = new Thickness(2), Content = item };
Binding b = new Binding();
b.Source = reset;
b.Path = new PropertyPath("SomePropertyOnDataContext");
newButton.SetBinding(Button.IsEnabledProperty, b);
Varying assumptions in the code...but it should give you an idea where to start...

Resources