I need to stretch a diagram and a grid in Telerik WPF RadGanttView control for the full windows width. But the diagram width stays 336 units anyway and 105 units for the grid. No property affects it. The code is:
<telerik:RadGanttView Grid.Row="1" HorizontalAlignment="Stretch" Margin="8,0,6,20" VerticalAlignment="Stretch"
TasksSource="{Binding GanttTasks}" Background="{DynamicResource backgroundBrush}" BorderBrush="{DynamicResource BorderBrush}"/>
Tell me please how can I increase the real width to the full window.
To provide a little more info for anyone else dealing with this...
The RadGanttView defaults to only displaying 7 days of information
This is defined as the VisibleRange of the control
The TimeRuler part of the control only expands to be wide enough to display the VisibleRange
If the VisibleRange is wider than the available display area, you can horizontally scroll, as expected and everything looks good
If the VisibleRange is narrower than the available display area, you wind up with a blank space to the right of the TimeRuler part of the control - which looks particularly bad when the window is maximized
To make the TimeRuler part of the control expand to use the available display area, you have to set the VisibleRange property on the control to a value that is high enough to extend beyond the available display area (e.g. 30+ days, etc.)
You can add a VisibleRange property to your view model and set the Start/End dates in the view model constructor (or wherever it makes sense for you):
VisibleRange = new VisibleRange
{
Start = DateTime.Today,
End = DateTime.Today.AddDays(60)
};
And then you can bind the VisibleRange property on the RadGanttView to the VisibleRange property you just added to your view model:
<telerik:RadGanttView x:Name="GanttView" TasksSource="{Binding Tasks}" VisibleRange="{Binding VisibleRange}" />
Not sure the answer is still needed here so i'll be be quick : you need to change the PixelLength. It is a timeSpan that you wanna have equal to your number of pixel in the right part viewport divided by the length of your project.
Related
I want to create a plot that dynamically displays active elements as rectangles. I have achieved a first version that is actually ok using OxyPlot.Annotations.RectangleAnnotation which I add to myPlotModel.Annotations, you can see it in the image hereafter:
Example of wanted display
The thing is that after a while, the amount of drawn rectangles make the update not smooth as I update the shown timewindow (which is set to 15 seconds). I have already set a maximum of drawn elements that suffice to cover the displayed window (i.e. the rectangles get removed as they are too far in the past), but the rendering is still jerky. I draw the rectangles by allocating them to an equal fraction of the Y-axis, that is the third one from the top gets:
rowNumber= 3.0
minimumY = maximalY - maximalY / totalElements * rowNumber
maximumY = maximalY - maximalY / totalElements * (rowNumber + 1.0)
And the Y-axis is hidden.
My question:
Is there a smarter way of creating such a display that would be less computationally heavy, and therefore allow a smoother update? I do not have to stick to OxyPlot, it is simply the easiest way that I found to obtain what I wanted.
Thanks for your answers!
Technically, the answer to your question is "Yes".
There are a number of ways to do this.
You could have a vertical itemscontrol that had an itemscontrol in it's template. That could have a canvas as it's itemspresenter and you could bind canvas.top and canvas.left to properties in it's content. Template each into a rectangle and bind height and width.
And of course do something about the scale on the bottom and the column of activity labels or whatever you want to call them there.
Unless you're using an absolutely ancient machine, that'd just fly.
It's quite a lot of work but it would probably be quicker to write that than to search through a load of alternative packages and decide which was optimal.
I'm trying to extend the standard TextBox control in the System.Windows.Forms namespace. One of the things I'm trying to accomplish is to modify padding on the top and bottom of the TextBox (the spacing between the text and the border).
Doing it on the left/right sides is pretty simple, but I'm having a hard time getting anything to work on the top/bottom.
Here are a couple of my requirements (if possible):
Avoid extending anything besides System.Windows.Forms.TextBox (no UserControls)
I want to keep MultiLine = false
This code allows me to resize vertically, and it adds a left padding:
public class TextBoxTest : TextBox
{
public TextBoxTest()
{
base.AutoSize = false;
NativeMethods.SendMessage(Handle, NativeMethods.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN, 20);
base.Height = 55;
base.Width = 150;
base.Text = "This is a test";
}
}
This will look like:
I also tried EM_SETRECT but it requires a MultiLine TextBox.
Is a top/bottom margin (or center vertically) possible - without using a UserControl and keeping MultiLine=false?
If so, can someone point me in the right direction?
UPDATE, to clarify, the reason I want to inherit from TextBox, and not a UserControl or Panel is so it passes the duck test (if it looks like a duck, quacks like a duck, etc). I want if (myControl is TextBox) ... to evaluate to true. There may be a way to do that, I haven't done much with Type Converters and maybe that's the path I should be taking.
I want this to be a true extension of a TextBox. In other words, it can do just about everything a textbox can do plus some, but no limitations due to the fact that it's not of type "TextBox". It seems like there's gotta be a way to adjust it somehow, it supports left and right margins but seemingly not upper/lower margins. Thanks again
You cannot change the padding property of Windows forms textbox from your code.
Instead you can place a textbox in a container, like a panel
remove the border of the textbox, make sure that the BackColor property for both is same
change the Dock property of the textbox to Fill
and then apply padding to the panel.
I'm working on a LineGraph control which consists many DependencyProperties that affect how the control should display its data. For example, the control contains the following properties to affect its axes:
AxisStroke - Color of the axes.
AxisThickness - Stroke thickness of the axes.
It also contains properties for display numbers & tick marks
VerticalTicks - True/False to indicate whether or not ticks appear along the vertical axis
HorizontalTicks - True/False to indicate whether or not ticks appear along the horizontal axis
VerticalMin - Minimum value on the vertical axis (numeric)
VerticalStep - The distance in between each vertical tick
VerticalMax - Maximum value on the vertical axis (numeric)
HorizontalMin - Minimum value on the horizontal axis (numeric)
HorizontalStep - The distance in between each horizontal tick
HorizontalMax - Maximum value on the horizontal axis (numeric)
And many more properties exist to allow for different line styles on a single graph (LineColor, LineThickness, DataPointShape, and DataPointIcon to name a few).
My goal is to be able to call out my LineGraph in XAML to insert it into a Window. I would like to be able to specify each of these settings inside the XAML as well, and see the new rendered image of the control in the WPF designer.
Now, given there is a lot of geometric shapes to render on the LineGraph, I though using a Canvas would be a good choice to render the data. Unfortunately, when I'm working in XAML, I cannot perform computations for the locations of shapes based on the control's width & height.
And yes, the shapes' locations must be computed because the data points for the graph are dynamic and the tick-related information is dynamic. Not to mention, I would like to display the actual values along each axis of the LineGraph.
So, I thought I might be able to display this control as if I was doing the rendering in C# code. Other windowing frameworks sometimes provide a Render method that can be used for laying out all of the sub-components.
Doing this, however, doesn't seem possible since WPF relies heavily on XAML for the visual appearance of controls. Also, requiring that the WPF designer must display the LineGraph based on the properties and data specified, it doesn't seem like C# code would solve the problem.
I suppose my questions are these:
How can I render data dynamically inside of a WPF control?
Am I able to specify in C# how my control is rendered, allowing the WPF designer to reflect it?
Side Note:
I've done quite a bit of research, but I am only finding information on how to implement more simple types of controls. If you know of any references that contain information on this topic, please feel free to post them in addition to your answers. I will be more than happy to learn how to do this completely.
EDIT:
I've created a graph using Excel to elaborate what the LineGraph control might look like if it has correct data and properties.
I will answer this based on my experience on implementing custom built graphing libraries in WIN32, WinForm, WPF, WinCE, WP8+WinRT, ....and even on a FPGA :)
It's extremely difficult to implement one from scratch. It may seem easy at first but you will run into a lot of "What should I do if this happens?". For example, in your above graph it seems you got a DataPoint # (5,100) it graphs it pretty well. But lets say, I add another DataPoint # (5.000000005, 0). How would you handle that in your code? Would you say that each pixel on the graph represents an exact value on the X-Axis, or does each pixel represent a range of X-Values?
I would recommend that you use an already establish library to do what you want to do unless you need something very specific like lets say you need horizontal cursors on the graph (think Tektronix Oscilloscope) and you need to calculate some values in between the two cursors.. then maybe you need to implement your own custom one or build on top of an open source one.
So, if you are still adamant of creating your own custom control here are answers to your questions.
How can I render data dynamically inside of a WPF control?
You can use a WriteableBitmap and create your own primitive drawing library from that. After you're done rendering, set it as the ImageSource of your control.
Or you can use WriteableBitmapEx which has GDI like drawing functions already implemented for you.
WriteableBitmapEx CodePlex Page, I also think you can just get it from NuGet as well.
You can also use a <Canvas> and add UI elements to that as well.
Am I able to specify in C# how my control is rendered, allowing the WPF designer to reflect it?
This depends on how you create your controls, but yes you can create Properties in your custom control that will appear in the Designer. Allowing you to change it thus updating the display. I would read a lot of tutorials about writing your own custom user control library. They can explain it better than I can in a SO answer. If you implement the properties correctly it should like so.....
Full Size Image: http://i.stack.imgur.com/pmevo.png
After changing the Number of Rows from 15 to 10 and the starting Y offset to -1 (thus moving the graph up and making the rows a lot taller)
Full Size Image: http://i.stack.imgur.com/0RKnA.png
In Xamarin.Forms every View has the two properties HorizontalOptions and VerticalOptions. Both are of type LayoutOptions and can have one of the following values:
LayoutOptions.Start
LayoutOptions.Center
LayoutOptions.End
LayoutOptions.Fill
LayoutOptions.StartAndExpand
LayoutOptions.CenterAndExpand
LayoutOptions.EndAndExpand
LayoutOptions.FillAndExpand
Apparently it controls the view's alignment on the parent view. But how exactly is the behavior of each individual option? And what is the difference between Fill and the suffix Expand?
Short answer
Start, Center, End and Fill define the view's alignment within its space.
Expand defines whether it occupies more space if available.
Theory
The structure LayoutOptions controls two distinct behaviors:
Alignment: How is the view aligned within the parent view?
Start: For vertical alignment the view is moved to the top. For horizontal alignment this is usually the left-hand side. (But note, that on devices with right-to-left language setting this is the other way around, i.e. right aligned.)
Center: The view is centered.
End: Usually the view is bottom or right aligned. (On right-to-left languages, of course, left aligned.)
Fill: This alignment is slightly different. The view will stretch across the full size of the parent view.
If the parent, however, is not larger then its children, you won't notice any difference between those alignments. Alignment only matters for parent views with additional space available.
Expansion: Will the element occupy more space if available?
Suffix Expand: If the parent view is larger than the combined size of all its children, i.e. additional space is available, then the space is proportioned amongst child views with that suffix. Those children will "occupy" their space, but do not necessarily "fill" it. We'll have a look on this behavior in the example below.
No suffix: The children without Expand suffix won't get additional space, even if more space is available.
Again, if the parent view is not larger than its children, the expansion suffix does not make any difference as well.
Example
Let's have a look on the following example to see the difference between all eight layout options.
The app contains a dark gray StackLayout with eight nested white buttons, each of which is labeled with its vertical layout option. When clicking on one of the buttons, it assignes its vertical layout option to the stack layout. This way we can easily test the interaction of views with parents, both with different layout option.
(The last few lines of code add additional yellow boxes. We'll come back to this in a moment.)
public static class App
{
static readonly StackLayout stackLayout = new StackLayout {
BackgroundColor = Color.Gray,
VerticalOptions = LayoutOptions.Start,
Spacing = 2,
Padding = 2,
};
public static Page GetMainPage()
{
AddButton("Start", LayoutOptions.Start);
AddButton("Center", LayoutOptions.Center);
AddButton("End", LayoutOptions.End);
AddButton("Fill", LayoutOptions.Fill);
AddButton("StartAndExpand", LayoutOptions.StartAndExpand);
AddButton("CenterAndExpand", LayoutOptions.CenterAndExpand);
AddButton("EndAndExpand", LayoutOptions.EndAndExpand);
AddButton("FillAndExpand", LayoutOptions.FillAndExpand);
return new NavigationPage(new ContentPage {
Content = stackLayout,
});
}
static void AddButton(string text, LayoutOptions verticalOptions)
{
stackLayout.Children.Add(new Button {
Text = text,
BackgroundColor = Color.White,
VerticalOptions = verticalOptions,
HeightRequest = 20,
Command = new Command(() => {
stackLayout.VerticalOptions = verticalOptions;
(stackLayout.ParentView as Page).Title = "StackLayout: " + text;
}),
});
stackLayout.Children.Add(new BoxView {
HeightRequest = 1,
Color = Color.Yellow,
});
}
}
The following screenshots show the result when clicking on each of the eight buttons. We make the following observations:
As long as the parent stackLayout is tight (does not Fill the page), the vertical layout option of each Button is negligible.
The vertical layout option only matters if the stackLayout is larger (e.g. via Fill alignment) and the individual buttons have the Expand suffix.
Additional space is evently proportioned amongst all buttons with Expand suffix. To see this more clearly we added yellow horizontal lines between every two neighboring buttons.
Buttons with more space than their requested height do not necessarily "fill" it. In this case the actual behavior is controlled by their alignment. E.g. they are either aligned on top, center or button of their space or fill it completely.
All buttons span across the whole width of the layout, since we only modify the VerticalOptions.
Here you find the corresponding high-resolution screenshots.
There is a bit of a bug in the current version of Xamarin.Forms; maybe it has been there a while.
CenterAndExpand generally doesn't expand, and working around it can be confusing.
For example if you have a StackLayout set to CenterAndExpand, then you put a label inside that also set to CenterAndExpand you would expect a label that is full width of the StackLayout. Nope. It won't expand. You have to set the StackLayout to "FillAndExpand" to get the nested Label object to expand to the full width of the StackLayout, then tell the Label to center the text, not itself as an object, with HorizontalTextAlignment="Center". In my experience you need both the parent and nested child to be set to FillAndExpand if you really want to make sure it expands to fit.
<StackLayout HorizontalOptions="FillAndExpand"
Orientation="Vertical"
WidthRequest="300">
<Label BackgroundColor="{StaticResource TileAlerts}"
HorizontalOptions="FillAndExpand"
Style="{StaticResource LabelStyleReversedLrg}"
HorizontalTextAlignment="Center"
Text="Alerts" />
Falko gave a good explanation but I wanted to add onto that with another visual and how these tags work in xaml, which is what I prefer to use most of the time. I made a simple project for testing out display results. Here is the Xaml for the Main Page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Alignments.MainPage"
BackgroundColor="White">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="LightGray" Padding="1" Margin="30">
<Label Text="Vert: EndAndExpand, Horz: EndAndExpand" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" BackgroundColor="White"/>
</StackLayout>
</ContentPage>
As you can see it's a very simple StackLayout with a Label inside. For each image below I kept the StackLayout the same, I just changed the horizontal and vertical options for the Entry and changed the text to show the selected options, so you can see how the Entry moves and resizes.
Here is the code used for Start:
<Label Text="Vert: Start, Horz: Start" VerticalOptions="Start" HorizontalOptions="Start" BackgroundColor="White"/>
And the code used for StartAndExpand:
<Label Text="Vert: StartAndExpand, Horz: StartAndExpand" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" BackgroundColor="White"/>
As you can see there is no difference visually other than there is more text used in the StartAndExpand option. This was tested on my Samsung A30 physical device. These may display differently on different devices, but I think all of the images here collectively show that there are some bugs in Xamarin. For the rest I will just show the screenshots, I think they are self-explanitory.
I also recommend taking a look at the Microsoft documentation for some additional details. Notable is that "Expansion is used only by a StackLayout".
How do you get the REAL position of objects in silverlight?
I have a header image centered on the screen. When I make the browser window smaller, obviously, the header's left side goes off the screen. Finding out the actual position is good to know if you want to position objects on top of the image.
I capture the Content_Resized and I run a little test:
if (App.Current.Host.Content.ActualWidth > header.Width)
{
TEST = Canvas.GetLeft(header);
}
else
{
TEST = Canvas.GetLeft(header);
}
TEST always returns zero.
EDIT: header sits on a grid instead of a canvas. "Well, there is your problem..." So a better question might be this. How would I get the margins of an image sitting on a grid?
I probably should just answer the question but how to find the position of an element relative to another is probably something that has been answered before (by myself and others) here and elsewhere on the tinternet.
However if your goal is to place an item over an image then place the image in a Grid and then add the item as child of the Grid. That way you assign the relative position over the image as the margin of the item and let Silverlight's layout system do the rest.
As a general rule if you feel that you need to write code to move stuff about when the size of things change then unless you are writing a custom panel or something you're probably not using Silverlight layout system properly.
Edit:
Try this experiment:-
<Grid x:Name="LayoutRoot">
<Grid x:Name="headerContainer" Margin="50, 60, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image Source="YourLargeImage" />
<Image Source="YourSmallerImage" HorizontalAlignment="Center" VerticalAlignment="Top" />
</Grid>
</Grid>
Now try changing the inner grid's Margin to move its position around the screen. Note the smaller image always remains at the top center of the large image.
I got it working.
First of all, these images are on a grid, not a canvas. But switching the grid to a canvas caused lots of other problems one of which is that I could not have the header image centered like before.
The solution was to change the margin of the smaller image sitting on top of the larger header image when the content resized like this:
blankbarimage.Margin = new Thickness((App.Current.Host.Content.ActualWidth - header.Width) / 2, 0, 0, 0);
and, by the way, you create a content resized method like this:
App.Current.Host.Content.Resized += new EventHandler(Content_Resized);
So, to answer my own question, the way you get the REAL position of object in silverlight is (if they are on a grid) by looking at their margin settings.