Well, this might be a strange question. But as title says, can you add Grid to ContainerVisual. Since Grid inherits Visual, I should be able to do it via Children.Add.
Why do I need this? Well, I'm using FlowDocument to print a report. This report needs to have a header, and since Flow Document doesn't support Headers, I decided to add headers during pagination, by using a solution found on the internet.
Also since I don't want to draw entire header by hand but be able to edit it during desing in a designer, I designed it in a separate file as a Grid element.
So my header looks something (I shortened it) like this:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="2cm" Width="18.7cm">
<Grid.Resources>
<!-- some resources -->
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2cm"/>
<ColumnDefinition/>
<ColumnDefinition Width="2cm"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.RowSpan="2">
<Image Source="Logo.jpg"/>
</Border>
<Border Grid.Column="1" Grid.RowSpan="2">
<StackPanel>
<Label Name="staje" Style="{DynamicResource naslov}"></Label>
<Label Name="predmet" Style="{DynamicResource naslov}"></Label>
</StackPanel>
</Border>
<Border Grid.Column="2" BorderThickness="1">
<StackPanel>
<TextBlock>Datum:</TextBlock>
<Label Name="datum">22. 12. 2013.</Label>
</StackPanel>
</Border>
<Border Grid.Column="2" Grid.Row="1" BorderThickness="1,0,1,1">
<StackPanel>
<TextBlock>Strana:</TextBlock>
<Label Name="strana">
1/2
</Label>
</StackPanel>
</Border>
</Grid>
at each pagination call I load the header using the folowing code:
public FrameworkElement GetHeaderForPage(int Strana)
{
FrameworkElement header = Application.LoadComponent(new Uri("/Header.xaml", UriKind.Relative)) as FrameworkElement;
Label lblTest = LogicalTreeHelper.FindLogicalNode(header, "staje") as Label;
Label lblPredmet = LogicalTreeHelper.FindLogicalNode(header, "predmet") as Label;
Label lblDatum = LogicalTreeHelper.FindLogicalNode(header, "datum") as Label;
Label lblStrana = LogicalTreeHelper.FindLogicalNode(header, "strana") as Label;
lblTest.Content = KakavTest;
lblPredmet.Content = Predmet;
lblDatum.Content = Datum;
lblStrana.Content = string.Format("{0}", Strana);
return header;
}
And finally in the pagination call I place it in the page like so:
DocumentPage page = m_Paginator.GetPage(pageNumber);
// Create a wrapper visual for transformation and add extras
ContainerVisual newpage = new ContainerVisual();
FrameworkElement header = headerGen.GetHeaderForPage(pageNumber);
// header.RenderTransform = new TranslateTransform(0, -header.ActualHeight+10);
ContainerVisual smallerPage = new ContainerVisual();
smallerPage.Children.Add(page.Visual);
//smallerPage.Transform = new MatrixTransform(0.95, 0, 0, 0.95,
// 0.025 * page.ContentBox.Width, 0.025 * page.ContentBox.Height);
newpage.Children.Add(smallerPage);
newpage.Children.Add(header);
newpage.Transform = new TranslateTransform(m_Margin.Left, m_Margin.Top);
RenderTargetBitmap bmp = new RenderTargetBitmap((int)m_PageSize.Width, (int)m_PageSize.Height, 96, 96, PixelFormats.Default);
bmp.Render(newpage);
ImageShow show = new ImageShow(bmp);
show.Show();
return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox));
ImageShow class simply opens up new window with an image representing bmp. I was using it to see if the problem was in further processing that is done to display the pages in DocumentViewer. But since ImageShow doesn't display the header Grid, it seems tht I'm doing something terribly wrong.
IN SHORT:
Can you add Grid element to ContainerVisual as a child and have it be drawn correctly. Or do I need to draw it by hand?
In the end I hard coded it all by hand. So no, anything that is higher than VIsual and DrawingVisual, can not be included into ContainerVisual.
Related
How can I programmatically convert my very wide GridView to a bitmap image? I need all the data to show in one bitmap image.
Xaml:
<StackPanel>
<telerik:RadGridView x:Name="GridView1" ItemsSource="{Binding MyProperties1}" AutoGenerateColumns="True" />
<telerik:RadGridView x:Name="GridView2" ItemsSource="{Binding MyProperties2}" AutoGenerateColumns="True" />
</StackPanel>
#Yanger Yang's answer is close, but you should use the element's DesiredSize instead of its ActualWidth/ActualHeight. This is, of course, assuming that you're not setting an explicit size on the Grid element itself. This approach should work with your telerik:RadGridView, but I do not have the library available for testing.
Here's a sample project containing a Grid with fifteen (15) columns inside a ScrollViewer.
<Window x:Class="PrintableGridDemo.MainWindow"
Title="Printable Grid" Height="600" Width="800">
<DockPanel>
<Button DockPanel.Dock="Top"
HorizontalAlignment="Right"
Margin="0 10 10 0"
Padding="50 10"
Content="Print"
Click="PrintButton_Click"/>
<Border Margin="10"
BorderBrush="DarkGray"
BorderThickness="1">
<ScrollViewer HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible">
<Grid x:Name="MyGrid"
Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</Border>
</DockPanel>
</Window>
I've (ab)used the class's constructor to populate the Grid with sample data including the column number so that you can see the generated image contains all the columns in the grid.
public MainWindow()
{
InitializeComponent();
for (int col = 0; col < MyGrid.ColumnDefinitions.Count; col++)
{
var control = new TextBlock() {
Text = $"This is column number { col + 1 }. It is a column with almost no dynamic data. The only dynamic data is the number corresponding to this column's index in the grid plus one since users prefer one-indexed values while the framework uses zero-indexed values.",
TextWrapping = TextWrapping.Wrap
};
MyGrid.Children.Add(control);
Grid.SetColumn(control, col);
}
}
Here's what the project looks like when it's running.
And here's the result of clicking the "Print" button. As you can see, using the DesiredSize of the grid has allowed us to see the contents of all columns (and has also removed the extra layout whitespace where the grid expanded to fill the ScrollViewer).
Here's what happens when you click the "Print" button:
private void PrintButton_Click(object sender, RoutedEventArgs e)
{
// Set up the output file.
string destination = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fileName = $"GridImage_{DateTime.Now:yyyy-MMM-dd_hh-mm-ss-tt}.png";
string filePath = Path.Combine(destination, fileName);
// Render the control as a Bitmap.
RenderTargetBitmap image = new((int)MyGrid.DesiredSize.Width, (int)MyGrid.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
image.Render(MyGrid);
// Encode the Bitmap image as a PNG instead.
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(image));
// Save the PNG to the file.
using FileStream stream = File.Create(filePath);
encoder.Save(stream);
}
The key bit is here:
RenderTargetBitmap image = new(
// The key bit.
(int)MyGrid.DesiredSize.Width,
(int)MyGrid.DesiredSize.Height,
// Format specific parameters. You can ignore these.
96, 96, PixelFormats.Pbgra32);
Because we're using the element's DesiredSize, the render will include parts of the element that would not normally be rendered (since they are not visible in the UI).
If you run into issues with clipping, you can call the element's Measure method to recalculate the element's current DesiredSize.
It is convenient to use DrawToBitmap in Windows Form to do what you want. In WPF, you can use RenderTargetBitmap, BitmapFrame and BmpBitmapEncoder to do that.
void SaveToBmp(FrameworkElement control, string fileName)
{
var bmpEncoder = new BmpBitmapEncoder();
SaveControlToImage(control, fileName, bmpEncoder);
}
void SaveControlToImage(FrameworkElement control, string fileName, BitmapEncoder encoder)
{
// Keep the current postion relative to the container
UIElement container = VisualTreeHelper.GetParent(control) as UIElement;
Point curPos = control.TranslatePoint(new Point(0.0, 0.0), container);
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
Size visualSize = new Size(control.ActualWidth, control.ActualHeight);
control.Measure(visualSize);
control.Arrange(new Rect(visualSize));
bitmap.Render(control);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
control.Arrange(new Rect(curPos, visualSize));
}
And using the following code to save your GridView to image file:
SaveToBmp(GridView1, #"D:\gridview1.bmp");
Refer to Easiest way of saving wpf Image control to a file and add some improvement.
I am making use of Font Awesome's icons to render basic font images within my C# WPF application. During run-time when I attempt to alter the TextBlock to display a different font icon but the unicode representation is displayed instead of the font icon.
I have created a sample application to display this. When either of the buttons are clicked, it replaces the TextBlock's Text property with the unicode for the respective icon. There is a Resources folder in the project which has the FontAwesome.ttf font file as a Build Resource which the The TextBlock's FontFamily property references.
Here's my sample application's source code:
Code-Behind:
namespace FontAwesomeTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnGlass_Click(object sender, RoutedEventArgs e)
{
tblkFontIcon.Text = "";
}
private void btnMusic_Click(object sender, RoutedEventArgs e)
{
tblkFontIcon.Text = "";
}
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
tblkFontIcon.Text = "";
}
}
}
XAML:
<Window x:Class="FontAwesomeTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Font Awesome Test Window" Height="300" Width="330" Name="FontAwesomeTestWindow">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Name="btnGlass" Height="35" Width="85" Click="btnGlass_Click" >Glass</Button>
<Button Name="btnMusic" Grid.Column="1" Height="35" Width="85" Click="btnMusic_Click">Music</Button>
<Button Name="btnSearch" Grid.Column="2" Width="85" Height="35" Click="btnSearch_Click">Search</Button>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" FontFamily="../Resources/#FontAwesome"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" FontFamily="../Resources/#FontAwesome"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" FontFamily="../Resources/#FontAwesome"></TextBlock>
<TextBlock Name="tblkFontIcon" Grid.Row="2" Grid.ColumnSpan="3" FontSize="64" FontFamily="../Resources/#FontAwesome" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
I used the following tutorial to incorporate Font Awesome into my application http://www.codeproject.com/Tips/634540/Using-Font-Icons
So in essence, how can I change the Icon but have an Icon display - not Unicode?
Thanks in advance.
Font Awesome has NuGet packages named FontAwesome.UWP and FontAwesome.WPF. Just download one of this.
If you will use a icon import follow namespace into your XAML code:
xmlns:fa="http://schemas.fontawesome.io/icons/"
Use it into your button like this:
<Button x:Name="btnButton">
<Button.Content>
<fa:ImageAwesome Icon="LongArrowLeft"/>
</Button.Content>
</Button>
And finally in your C# code behind:
using FontAwesome.WPF; // on the top of the code
btnButton.Content = FontAwesomeIcon.LongArrowRight;
UPDATE
I found a different post for this topic --
Add Icon font in wpf
I think this should be more likely to what you want.
Make sure your font is added as a resource. Then, use the following
string:
<Setter Property="TextElement.FontFamily" Value="pack://application:,,,/fonts/#FontAwesome" />
In the string above, I'm assuming that the font's name (not the
font's filename) is FontAwesome.
You just need to:
Add the Font to your project, let's say you put them in to a folder "fonts"
Change the Build Action to Resource not Embedded Resource
Add your style to set the font family like the code snip above, and set the TextBlock.Text to the icon you like and apply the style to the TextBlock.
If you want change the icon by updating the TextBlock.Text property, you should set the Text property with the supported unicode string.
Try something like
tblkFontIcon.Text = "\uf000";
rather than
tblkFontIcon.Text = "";
If your're using the code from Using Font Icons
then you probably missed the "How It Works" section in that post.
You should use that markup extension, rather than using the TextBlock.Text property.
In his sample code:
<RibbonButton Label="Import data"
LargeImageSource="{WpfTools:ImageFromFont Text=,
FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}" />
pay attention to the WpfTools:ImageFromFont, it is the Markup Extention, it allows xaml parser to convert the
{WpfTools:ImageFromFont Text=,
FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}
to an ImageSource and assigned to the LargeImageSource property.
So in your xaml, you could replace the TextBlock with an Image, then it should be something like:
<Image Source="{WpfTools:ImageFromFont Text=,
FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}" />
If you want to change the Icon, you will have to change the ImageSource yourself, just follow the Using Font Icons to create your own method, or simply copy the following code from that tutorial.
private static ImageSource CreateGlyph(string text,
FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight,
FontStretch fontStretch, Brush foreBrush)
{
if (fontFamily != null && !String.IsNullOrEmpty(text))
{
Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
GlyphTypeface glyphTypeface;
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
throw new InvalidOperationException("No glyphtypeface found");
ushort[] glyphIndexes = new ushort[text.Length];
double[] advanceWidths = new double[text.Length];
for (int n = 0; n < text.Length; n++)
{
ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
glyphIndexes[n] = glyphIndex;
double width = glyphTypeface.AdvanceWidths[glyphIndex] * 1.0;
advanceWidths[n] = width;
}
GlyphRun gr = new GlyphRun(glyphTypeface, 0, false, 1.0, glyphIndexes,
new Point(0, 0), advanceWidths,
null, null, null, null, null, null);
GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(foreBrush, gr);
return new DrawingImage(glyphRunDrawing);
}
return null;
}
Simple and very easy:
You should install fontawesome font on your system use it as follows
<Button Content="" FontFamily="FontAwesome" FontSize="32" />
How to compose icon, {&#x}{FontAwesome icon code} e.g  for address book
To find the list of codes goto FontAwesome or astronaut web
I am trying to fix a larger block of code written by previous colleague - it i some sort of report system, output is a table with data. My task was to freeze column headerson top when scrolling. As i am new to this, I made very simple table, to find out how datagrid works:
public MainWindow()
{
this.InitializeComponent();
var dt = new DataTable();
dt.Columns.Add("prvni");
dt.Columns.Add("druhy");
for (int i = 0; i < 100; i++)
{
var row = dt.NewRow();
row[0] = "A" + i;
row[1] = "B" + i;
dt.Rows.Add(row);
}
this.MainGrid.ItemsSource = dt.AsDataView();
}
By lots of searching, I found many topics, which recommended to get rid of ScrollViewer, as the freezed headers are in datagrid by default. This was the original part of code I modified:
var scrollViewer = new ScrollViewer()
{
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto
};
scrollViewer.AddHandler(UIElement.MouseWheelEvent, new RoutedEventHandler(this.MouseWheelHandler), true);
var stackPanel = new StackPanel();
scrollViewer.Content = stackPanel;
...
return scrollViewer;
And in another function, it was used/called as:
var reportInfo = ((((sender as DataGrid).Parent as StackPanel).Parent as ScrollViewer).Parent as ReportOutputTabItem).Tag as ReportInfo;
Well - I removed the scrollviewer, and was returning it as StackPanel, however - now I cannot scroll at all. When I searched questions, how to add vertical scrolling to StackPanel, answers were "add ScrollViewer".
So - is there a way, how either make column headers freezed inside the ScrollViewer, or how to enable vertical scrolling in StackPanel without using scrollViewer? (and another possible solution might be to make the vertical size of StackPanel bit shorter, as there are mostly pages of results, but full page is still required to scroll a bit).
XAML part:
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TabControl Name="MainTab" SelectionChanged="MainTabSelectionChanged" ItemTemplate="{StaticResource ClosableTabItemTemplate}"/>
<StackPanel Grid.Row="1" Name="NavigationPanel" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Height="23" Name="FirstButton" Width="40" Content="<<" Click="PageButtonClick" Opacity="0.75"/>
<Button Height="23" Name="PrevButton" Width="40" Click="PageButtonClick" Opacity="0.75" Content="<"/>
<Label Height="23" Name="PageNumberLabel" Width="70" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Content="1/1"/>
<Button Height="23" Name="NextButton" Width="40" Content=">" Click="PageButtonClick" Opacity="0.75"/>
<Button Height="23" Name="LastButton" Width="40" Click="PageButtonClick" Opacity="0.75" Content=">>"/>
</StackPanel>
Thanks in advance.
Well, I finally found solution to this:
Originally, the datagrid was wrapped in the StackPanel, and then in ScrollViewer. I removed the ScrollViewer, and replaces StackPanel with Grid.
Now I have both vertical scrollbars, and frozen column headers.
I removed the entire
var scrollViewer = new ScrollViewer()
{
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto
};
scrollViewer.AddHandler(UIElement.MouseWheelEvent, new RoutedEventHandler(this.MouseWheelHandler), true);
var stackPanel = new StackPanel();
scrollViewer.Content = stackPanel;
and replaced with simple var grid = new Grid();
and all stackPanel.Children.Add(dataGrid); replaced with grid.Children.Add(dataGrid);
I have been looking for over 30 minutes now, but I simply cannot figure out what the problem is.
I have a TabControl and its items are to be closed by the user. Since each TabItem is in a way connected to a custom control and several objects that each use quite a lot of memory, I would like to dispose all objects that are used together with this TabItem.
To make it clearer and save you a lot of code here the simplified situation:
<UserControl x:Class="myProject.GridFour"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ScrollViewer Height="Auto" Margin="0" Name="scrollViewer11" Width="Auto" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
<ScrollViewer Grid.Column="1" Height="Auto" Name="scrollViewer12" Width="Auto" Margin="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"></ScrollViewer>
<ScrollViewer Grid.Row="1"> Height="Auto" Name="scrollViewer21" Width="Auto" Margin="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
<ScrollViewer Height="Auto" Name="scrollViewer22" Width="Auto" Grid.Column="1" Margin="0" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"></ScrollViewer>
</Grid>
</UserControl>
Now I set the content of the corresponding tabitem:
GridFour myControl = new GridFour();
myTabItem.Content = myControl;
Also I have custom objects that each contain a grid, which is added as content to the scrollviewers of my user control:
class MyClass
{
internal Grid _grid = new Grid();
internal Image _image = new Image() {Width = Double.NaN, Height = Double.NaN HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Stretch = Stretch.Fill};
//... a lot of variables, data, images and methods...
}
MyClass[] myObject = new MyClass[4];
for(int i = 0; i < 4; i++)
{
myObject[i] = new MyClass();
myObject[i]._grid.Children.Add(_image); //that actually happens when I initialise the object, it is just to show how everything is connected
}
myControl.scrollViewer11.Content = myObject[0]._grid;
myControl.scrollViewer12.Content = myObject[1]._grid;
myControl.scrollViewer21.Content = myObject[2]._grid;
myControl.scrollViewer22.Content = myObject[3]._grid;
Now when the user would like to close the tabitem obviously I would also like to get rid of myControl and of every single object myObject.
I tried to call the Dispose method on them via IDisposable but that always throws a NullReferenceException and I simply cannot figure out why.
I should maybe mention that every single myObject is within a Dictionary<string, MyClass> but I remove the object from there before I call dispose.
class MyClass : IDisposable
{
internal Grid _grid = new Grid();
internal Image _image = new Image() {Width = Double.NaN, Height = Double.NaN HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Stretch = Stretch.Fill};
//... a lot of variables, data, images and methods...
public void Dispose()
{
// your custom disposing
_image = null; //or something like that
}
}
So you are removing a UI element and then trying to get the model to update, instead:
Why not bind the UI to a ObservableCollection list of your object. Then to remove you just need to remove from the list in the model (and dispose if you wish) but let the UI do it's job and simply relect the changes to the list. This is how WPF works best.
Read up on TabControl.ItemsSource Like here.
I implemented some cpu scheduling algorithm.and i want to show it in windows form application in c# graphically but i don't know how?
example:
I have these processes:
p1,p2,p3,p4,p5,p6,p7,p8,p9,...
p2 do its process before p1,and p1 before p6 and p6 before p3 and...
I want something like this to show it for me:
http://i.stack.imgur.com/zEWbG.jpg
also each process length change based on its own process time, and show process start time and end time too.
How can I make something like that?
thank u.
I would recommend using WPF. You could achieve this many different ways.
One example is a WPF Grid with multiple columns. You can set the width of the column as a proportion. Eg A width of "3*" would indicate a process that takes half the time as a width of "6*"
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="MainGrid" Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="4*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Rectangle Fill="LightBlue"/>
<Rectangle Grid.Column="1" Fill="LightGreen"/>
<Rectangle Grid.Column="2" Fill="LightPink"/>
<Label HorizontalAlignment="Center" VerticalAlignment="Center">P2</Label>
<Label Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center">P1</Label>
<Label Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center">P6</Label>
</Grid>
</Window>
This XAML code would produce this.
http://img835.imageshack.us/img835/4742/picturelx.png
You could programatically add columns using C# code-behind like this.
private void AddColumn()
{
//Create the columndefinition with a width of "3*"
ColumnDefinition column = new ColumnDefinition();
column.Width = new GridLength(3, GridUnitType.Star);
//Add the column to the grid
MainGrid.ColumnDefinitions.Add(column);
//Create the rectangle
Rectangle rect = new Rectangle();
rect.Fill = new SolidColorBrush(Colors.Beige);
MainGrid.Children.Add(rect);
Grid.SetColumn(rect, 3);
//Create the label
Label label = new Label();
label.VerticalAlignment = System.Windows.VerticalAlignment.Center;
label.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
label.Content = "P4";
MainGrid.Children.Add(label);
Grid.SetColumn(label, 3);
}