Here are my goals:
Using the WPF Toolkit, create a simple column chart with a linear Y-axis and a DateTime range X-axis.
Bind a collection of objects to the chart. Each object has a DateTime(X-axis data-point) and Int32(Y-axis data-point) properties.
Below is my current XAML. The XAML below has the axes I want however, the chart will not render any data:
<chartingToolkit:Chart Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Name="ColumnChart" Title="Records Loaded By Date"
VerticalAlignment="Top" Height="262">
<chartingToolkit:Chart.Axes>
<chartingToolkit:DateTimeAxis Interval="1" IntervalType="Days" x:Name="myDateTimeAxis"
Orientation="X" Title="Date">
<chartingToolkit:DateTimeAxis.AxisLabelStyle>
<Style TargetType="chartingToolkit:DateTimeAxisLabel">
<Setter Property="StringFormat" Value="{}{0:MM/dd}"/>
</Style>
</chartingToolkit:DateTimeAxis.AxisLabelStyle>
</chartingToolkit:DateTimeAxis>
<chartingToolkit:LinearAxis Orientation="Y" ShowGridLines="True" x:Name="myYAxis"
Title="Transactions Loaded"/>
</chartingToolkit:Chart.Axes>
<chartingToolkit:Chart.Series>
<chartingToolkit:ColumnSeries DependentValuePath="TransactionLoadCount"
IndependentValuePath="Date" ItemsSource="{Binding Path=LoadStats}"
IsSelectionEnabled="True">
</chartingToolkit:ColumnSeries>
</chartingToolkit:Chart.Series>
</chartingToolkit:Chart>
Note: When I remove the XML section <chartingToolkit:Chart.Axes>...</chartingToolkit:Chart.Axes> the data WILL APPEAR but not in a format I like.
Why doesn't the chart render my collection data?
Since you figured it out and posted it in comments, I will expand on other things to look for when this problem would occur. Note to readers that came here, the problem was that the list bound to the control needs to contain > 1 DateTime in the collection in order to display a chart. This is a bug in the WPF Toolkit library. This may be fixed in the current/future versions of WPF Toolkit.
If that didn't fix your problem:
Watch your output window for any binding expressions errors when the control is load. If the data context of the chart is set right, binding the items source to an unavailable collection will cause problems.
Make sure the DateTime values that are to be used on the DateTime axis have values that span across at least 2 days, or whatever your interval is set for. If it applies, try setting a Maximum or Minimum value.
Use the process of elimination to determine if its the X or Y axis causing the issue. Comment out the X axis XAML and see if the control displays the Y axis correctly. If so, comment out the Y axis and uncomment the X axis XAML and see if it displays correctly. If not you know your problem is with one of the axes (that wasn't commented out).
Check that your StringFormat is correct. Here I believe you could just use `Value="MM/dd"
Make sure you spelled your properties for IndependentValuePath and DependentValuePath correctly.
I found these to be the biggest issues during charting experiences so this is a checklist to follow when debugging issues. Hopefully this will answer many general questions. If it doesn't suffice as an answer, you should answer it yourself OP.
Related
i am building an application in WPF for a custom need. First i opted for custom controls, but later on figured out that much of what i needed was already implemented in Datagrid Control. However there is one small glitch:
The problem with Datagrid is that it enforces a minimum of 2 pixel gap between two consecutive cells (1 on each side of the Grid Line). Please have a look at the following diagram for clarity:
.
Please note the 2 pixels gap enforced by the Datagrid between the two consecutive cells:
http://img265.imageshack.us/img265/3545/figurem.png
(Stack overflow wouldn't let me add image to my question citing a spam protection policy for new users)
.
This doesn't suit my requirement as i want the content to appear "continuous" (There must not be this gap of 2 pixels; i want the connecting lines to look "connected"). i've tried fidgeting with the GridLinesVisibility, but it didn't help. The DataGrid is hosting a custom control like this:
<DataGrid.Columns>
<DataGridTemplateColumn Width="25" Header="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=MyCustomControl}" Margin="0"></ContentControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
....
</DataGrid.Columns>
i have so far tried:
Switching off the GridLine (see result here: http://img263.imageshack.us/img263/8602/figure2j.png)
Setting the margin of the content property to 0.
Searched google and stackoverflow
Consulted some books.
but nothing seems to come up.
Is there a solution to this/some hack or a workaround or would i have to create everything from scratch? i have decent experience with c#, but i am new to WPF.
Please Help.
What you need to do is get at the DataGridCell style for your DataGrid and set its BorderThickness to be 0. It's hard-coded as 1 in the default style, but fortunately it's easy to override this:
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0" />
</Style>
I would suggest putting that into the resources of your DataGrid so it only affects that one grid, unless you want it to have a wider scope than that.
<DataGrid>
<DataGrid.Resources>
<Style TargetType="DataGridCell">...</Style>
</DataGrid.Resources>
...
</DataGrid>
There are other places you could put it as well, depending on your precise needs.
i'm trying to figure out how to layout a simple dialog in WPF using the proper dialog units (DLUs).
i've come up with a simpler example, that cuts straight to the problem:
You can check the Windows UX Guidelines to see where these measurements come from.
The short version is:
dlu = dialog unit
dlu is based on the font size (items change with user's font size)
a horizontal dlu is different from a vertical dlu (dlu's are not square)
This comes from the definition of a dialog unit: the average character is 8dlus high by 4dlus wide.
Georgia 14pt:
If you use a smaller font (i.e. 8pt Tahoma verses 14pt Georgia), the dlus get smaller:
Segoe UI 9pt:
Note: You'll notice that resolution (i.e. dpi) has no impact on the discussion.
You could try creating a Converter which returns the value multiplied by whatever your DLU is
For example, I created a MathConverter (code is here) which would let you specify something like
<Button Height="{Binding Source={x:Static local:Settings.VerticalDLU,
Converter={StaticResource MathConverter},
ConverterParameter=#VALUE*14}"
Width="{Binding Source={x:Static local:Settings.HorizontalDLU,
Converter={StaticResource MathConverter},
ConverterParameter=#VALUE*50}" />
To make it easier to write and read, you can create a class that inherits from Binding and setup a default binding properties so all you have to do is
<Button Height="{local:MyVDluBinding Source=14}"
Width="{local:MyHDluBinding Source=50}" />
I've never tried overwriting a binding with defaults for Converter and ConverterParameter, but I have overwritten a binding for validation purposes so I believe it's possible.
The ValidationBinding I created could be used like Text="{local:ValidationBinding MyProperty}" and automatically set ValidatesOnDataError=True, ValidatesOnException=True, UpdateSourceTarget=PropertyChanged in the bindings.
When you create a RowDetailsTemplate in a Silverlight grid you can specify a template for row details that is shown directly below the row when it is selected.
The details I have for one of my datagrids would look a lot better immediately before each individual row, rather than after it.
I've tried modifying the template in Blend, but end up getting stuck when I get to this part of the template:
<sdk:DataGridRowsPresenter x:Name="RowsPresenter"
Grid.ColumnSpan="2" Grid.Row="1"/>
There does not seem to be an associated template for DataGridRowsPresenter so I cannot seem to find how I might be able to move the details above the row.
Is this possible?
My work associate found this solution. It works in Expression Blend 4 using .NET 4
Create a project containing the datagrid. This works in Silverlight as well as WPF. On the datagrid, use "Edit Additional Templates" and create a copy of the RowStyle. Edit the RowStyle, and you'll see where the following lines are:
<sdk:DataGridRowHeader x:Name="RowHeader"
sdk:DataGridFrozenGrid.IsFrozen="True" Grid.RowSpan="3"/>
sdk:DataGridCellsPresenter x:Name="CellsPresenter" Grid.Column="1"
sdk:DataGridFrozenGrid.IsFrozen="True"
sdk:DataGridDetailsPresenter x:Name="DetailsPresenter" Grid.Column="1" Grid.Row="1"
The DataGridCellsPresenter and the DataGridDetailsPresenter are classes in the System.Windows.Controls.Primitive namespace.
What you do is interchange the Cells Presenter and the Details Presenter, save the style, and assign the style to the DataGrid RowStyle property. Your details will then appear above the row cell elements.
I don't know of a way besides Blend to get the entire Row Style.
I'm working on a WPF application which must handle multiple screens (two at this this time).
One view can be opened on several screens and user actions must be reflected consistently on all screens.
To achieve this, for a given type of view, a single DataContext is instantiated. Then, when a view is displayed on a screen, the unique DataContext is attached to it. So, one DataContext, several views (same type of view/xaml).
So far so good. It works quite well in most cases.
I do have a problem with a specific view which relies on ItemsControl. These ItemsControl are used to display UIElements dynamically build in the ViewModel/DataContext (C# code). These UIElements are mostly Path objects. Example :
<ItemsControl ItemsSource="{Binding WindVectors}">
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Canvas IsItemsHost="True" />
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
Here, WindVectors is a ObservableCollection<UIElement>.
When the view is opened the first time, everything is fine. The problem is that when the view is opened one another screen, all ItemsControl are removed from the first screen and displayed one the second screen. Other WPF components (TextBlock for instance) on this view react normally and are displayed on both screens.
Any help would be greatly appreciated.
Thanks.
Fabrice
This is the expected behavior (ie been that way since winforms)- this is because the ObservableCollection is a reference. This wont happen with value types, only reference types.
The short answer is 'dont do that'. You could try looking into defining a collection view in the xaml or code a custom data provider and bind to one of those instead.
I'm working on a Prism Composite application where I load different views into a region. I need to make sure that the view I'm loading is resized to the same height as the region. Each view is a usercontrol that has a Grid as the outer element. I'm using the following code
<Grid Height="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}, Path=ActualHeight}">
To set the height of the grid. My problem is that this exact code works fine for one view and doesn't for another view. On the grid that doesn't work, the height is what I would expect as if the Height property is not being set.
Any suggestions on how to trouble shoot this.
Without knowing much, I'd say this issue really just boils down to a binding issue. Debugging bindings is tricky, but there is a really great article on the subject here:
http://www.beacosta.com/blog/?p=52
Use the "diagnostics:PresentationTraceSources.TraceLevel=High" approach that Bea describes and find out what element you are actually binding to by watching the output window. That ought to help figure out why it's failing.
Good luck.