I have read so much material and tried so many things over the past week and I am not getting anywhere with this.
I have a main window MainWindowView which has checkboxes as defined below:
<CheckBox IsChecked="{Binding Path=ocv_checkbox, Mode=TwoWay}" Margin="0, 0, 0, 2" Content="OCV"/>
<CheckBox IsChecked="{Binding Path=battery_temperature_checkbox, Mode=TwoWay}" Margin="0, 0, 0, 2" Content="Battery Temperture"/>
<CheckBox IsChecked="{Binding Path=slope_checkbox, Mode=TwoWay}" Margin="0, 0, 0, 2" Content="Slope"/>
Depending on which boxes are checked, I want to plot a line on a graph when the user clicks a Button. I want all lines on the same graph.
The issue is that depending on the box clicked I may need an additional axis to plot on. For example, if I have 3 checkboxes 1 2 and 3. Number 1 and 2 have units of inches and checkbox 3 has units of gallons. If all 3 are checked, I will need a vertical axis for inches on the left (or right) side and an axis for gallons of the right side (to plot 3).
How do I do that programatically using D3? There is not much documentation at all and I have need seen a clear answer online.
Currently I have:
<d3:ChartPlotter Name="plotter" Margin="10,10,20,10">
<d3:ChartPlotter.HorizontalAxis>
<d3:HorizontalIntegerAxis Name="dateAxis"/>
</d3:ChartPlotter.HorizontalAxis>
<d3:ChartPlotter.VerticalAxis>
<d3:VerticalIntegerAxis Name="countAxis"/>
</d3:ChartPlotter.VerticalAxis>
<d3:Header FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=title}"/>
<d3:VerticalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=yAxis}"/>
<d3:HorizontalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=xAxis}"/>
</d3:ChartPlotter>
in my GraphWindowView.xaml which obviously only has 2 axes. I would like to add one using the code behind if possible.
Thank you,
Rich
If you want to add multiple Y axis, go for the InjectedPlotter object. Foreach type of data (inch, gallons...), you will need an InjectedPlotter that you add as a children to your chartplotter. When all the lines of one kind of data are disabled (checkboxes unchecked), just hide the injected plotter. You have to link each lines with his correct axis (injected plotter).
Related
is there an easy way to use a calculated property in a view?
I need to give a left padding proportional to an actual width of a grid, or the width of a column.
For example if I tilt the phone the grid gets wider and I want to update the padding.
This seems to work, but I want to calculate a value from the width, for example width/50:
<Label Text="Seg"
Style="{StaticResource subTitleLightTextStyle}"
Grid.Row="1"
Padding="{Binding Source={x:Reference bodyCalendar},
Path=Width}"
Grid.Column="1" />
I am using UWP and working with the Composition API to programmatically scale child text visuals that are nested in a typical XAML hierarchy. The textblocks in our app are contained in things like borders and a number of those borders are items contained in a GridView.
In many of the scenarios I am experiencing clipping of the associated text visual as it scales to be larger than some of the XAML containers that host the elements and I would like the visual to not get clipped as it scales to be larger than its parent.
Here is a barebone example that demonstrates some of the problems I am seeing…
My test app starts as a blank UWP app and the root grid of my page contains the following Gridview:
<GridView >
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" CornerRadius="5" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 1" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 2" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 3"/>
</Grid>
</Border>
</GridViewItem>
</GridView>
The codebehind file contains the following additional using statements, a variable declaration, variable initialization in page constructor and this event handler:
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml.Hosting;
Compositor compositor;
public MainPage()
{
this.InitializeComponent();
compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
}
private void Border_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var content = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(sender as FrameworkElement, 0), 0);
var visual = ElementCompositionPreview.GetElementVisual(content as FrameworkElement);
var animation = compositor.CreateVector3KeyFrameAnimation();
animation.InsertKeyFrame(0f, new Vector3(1.0f, 1.0f, 0.0f));
animation.InsertKeyFrame(0.5f, new Vector3(3.0f, 3.0f, 0.0f));
animation.InsertKeyFrame(1f, new Vector3(1.0f, 1.0f, 0.0f));
animation.Duration = TimeSpan.FromMilliseconds(5000);
visual.StartAnimation(nameof(visual.Scale), animation);
}
When you run the app and click on each of the strings you should initially notice that the first string behaves differently than the other two string.
The first string gets cropped at the Border's bounding box whereas the other two strings do not.
Also note that the other two strings appear to scale past the bounds of last item and out into the page, but that turns out to probably be due to the gridview autosizing to fill the page.
The difference between the first string and the other two is that the border has a corner radius property set on it. We use cornerradius setting in our application, so it would be nice to know if there is a way to override or control this behavior so that it doesn't clip the visual as it scales.
The other behavior that is causing us problems is that at the GridView bounds is another boundary that the visual is clipping at as it scales. If you set any property (like HorizontalAlignment="Center") on the Gridview that causes it to size itself to only be as big as it needs to be, then the visual gets cropped at the controls boundaries.
Is there anything within the Compositional API that allows me to prevent or influence this clipping behavior?
Have a checkbox with custom control template which looks like this in design view:
XAML code:
<CheckBox IsChecked="{Binding Fareklasse21}" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1">
<CheckBox.Template>
<ControlTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<Image Source="pack://application:,,,/Asd.WWs.Client.Wpf;component/Resources/ADR-M.png" Width="64" Height="64" SnapsToDevicePixels="True">
</Image>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type CheckBox}}}"></CheckBox>
<TextBlock>2.1</TextBlock>
</StackPanel>
</StackPanel>
</ControlTemplate>
</CheckBox.Template>
When I start the application, the image (which is originally 64x64px) gets distorted (and enlarged?)
Could it be that the image inherits some value from the Prism wrapper? I can't really see anything interesting while doing live inspection:
Here are the properties of the specific image:
The WPF graphics system uses device-independent units to enable resolution and device independence. Each device independent pixel automatically scales with the system's dots per inch (dpi) setting. This provides WPF applications proper scaling for different dpi settings and makes the application automatically dpi-aware. See also wiki page.
This is the reason why if you even specify Stretch=None for an Image control, you may notice that the image does not appear at the expected number of pixels wide/high. This can happen if the image’s resolution (DPI) doesn’t match your current system DPI.
The conversion from physical pixels to DIPs uses the following formula.
DIPs = pixels / (SystemDPI / 96.0)
If you want to convert DIP to the "real" pixels you can use next formula:
Width (pixels) = Width (WPF Units) * (SystemDPI / 96)
Height (pixels) = Height (WPF Units) * (SystemDPI / 96)
You can specify element size in DIP, inches, centimeters or points. But it's better to use vectorized graphics if possible.
If you have SVG files you can use sharpvector framework via nuget:
Install-Package SharpVectors
So there is SvgViewbox to render SVG in XAML:
<UserControl ...
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
...>
...
<svgc:SvgViewbox Margin="5" Height="20" Width="20" Stretch="Uniform" Source="/Resources/Icons/Sample.svg"/>
...
</UserControl>
I'm plotting a histogram of a grayscale image using an array of 256 values. Im doing so by creating my own chart with 256 vertical rectangles (columns). My aim is that first rectangle fill color to be red and the last rectangle to be blue. All the rectangles in between to be filled with a solid color which will make the transition from the first (red) to last (blue) smooth, like achiving a gradient with a rectangle step in changing the color.
When you look to the code, you can see that I'm able to fetch the index value of each element (rectangle) from the array. This is encapsulated in AlternationIndex and I'm thinking that the solution should use this in order to manipulate the Fill color value. Is it possible than to have a pure XAML solution for this ?
So the transition should look something like:
Here is my XAML code
<ItemsControl ItemsSource="{Binding HistogramValues}" AlternationCount="{Binding Path=HistogramValues.Count}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Height="{Binding}" ToolTip="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContentPresenter}}" Width="3" VerticalAlignment="Bottom" Fill="Black"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Where in view model I have:
public float[] HistogramValues { get; set; }
Write a custom converter which will pass an AlternationIndex & AlternationCount as parameters, and which spits out the color.
You can do linear interpolation between colors given those two parameters:
R = firstCol.R * p + secondCol.R * (1 - p)
The formula is quite easy, firstCol is the start color, secondCol is the end color.
p stands for current percentage, which can be calculated as currentAlternationIndex / AlternationCount.
You can do such calculation for each component(R, G, B), and your converter can return SolidColorBrush with concrete components.
Not sure though what you mean by pure Xaml solution. If you mean no converters, then there probably isn't one that is decent enough to mention here.
The other solution is to switch from height model into line model. Instead of ItemsControl, perhaps you can use Polyline to draw the data & then the gradient problem will be trivial.
I have created a Rectangle inside of a ScrollViewer like this
<ScrollViewer ManipulationMode="Control" x:Name="songScrollViewer" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" Height="270" VerticalAlignment="Center" Width="728" Canvas.Top="20" d:LayoutOverrides="HorizontalMargin" >
<Rectangle x:Name="musicBG" Fill="#FF0692FD"/>
</ScrollViewer>
During the use of the app, the size of MusicBg changes, sometimes to something around 3,000 pixels width.
musicBG.Width = _songLength*PixelsPerSecond
However, while scrolling the scrollViewer, it allows me to scroll the rectangle all the way off the screen.
For example this line of code gives me the following values when I have moved the rectangle as far as I want to move it.
if (songScrollViewer.HorizontalOffset > songScrollViewer.ScrollableWidth)
HorizontalOffset has a value of ~1200 and ScrollableWidth has a value of about ~2900.
How can I get this to be done properly so that the rectangle is not scrolled completely off the screen?
I would expect a HorizontalOffset of about 1200 to only push the rectangle about halfway through to it's destination, and not make it start going off screen.
ANSWER:
After much frustration, I was able to solve this problem by using Canvas instead of Border or Rectangle.
I'll award points if anyone can explain why this problem happened, and if there is a less processor intensive control that would work better than canvas.
Edit: Screen shots:
Bad Code:
<ScrollViewer ManipulationMode="Control" x:Name="songScrollViewer" Width="720" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" Height="270" VerticalAlignment="Top" Canvas.Top="20" HorizontalAlignment="Left" >
<Border x:Name="musicBG" Background="#FF0692FD" VerticalAlignment="Top" HorizontalAlignment="Left" Height="270" />
</ScrollViewer>
Image of bad scroll with bad code:
Good working code:
<ScrollViewer ManipulationMode="Control" x:Name="songScrollViewer" Width="720" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" Height="270" VerticalAlignment="Top" Canvas.Top="20" HorizontalAlignment="Left" >
<Canvas x:Name="musicBG" Background ="#FF0692FD" Height="270" >
<Border Background="#FF0692FD" VerticalAlignment="Top" HorizontalAlignment="Left" Height="270" />
</Canvas>
</ScrollViewer>
Good Scroll: Notice it says 170 seconds on the bottom right instead of the smaller number of 118 seconds in the bad scroll.
I believe your right, wp7 won't render shapes that are bigger then 2048 pixels. So the reason it's scrolling of the page is because it's treating it as if it were bigger then 2048 but you can only see up to a width of 2048px and its just scrolling over to the "ghost" part of the rectangle.
I'm not sure if you can override this but the best solution I could come up with (without overriding) is by splitting up your rectangle into chucks that are smaller then 2000 (just to be safe) and then displaying them seamlessly in a horizontal stack panel inside the scroll viewer. The problem with this is that depending on how you've coded it, this solution might be hard to implement; but you might just be able to split it in your ViewModel when displaying it and your logic would only see it as one big chunk.