I'm wondering if there is any way I can create a "table like" ListView in a UWP Windows 10 app? I need some sort of table where I can allow a user to browse and select files and then put the selected files into a list, sort of like a details view that you see in Windows explorer with column headers and rows that I can insert programmatically like:
string[] item = { "D:\\Music\\MyAudioFile.mp3", "MP3", "12MB" }
listview1.Items.Add(item);
Anyone have any ideas what I can use for this?
Thanks
Thanks Lindexi, that pointed me in the right direction... Here is the code I got working...
C# backend code:
// Create a new StackPanel to insert as a ListViewItem
StackPanel myStack = new StackPanel();
myStack.HorizontalAlignment = HorizontalAlignment.Stretch;
myStack.VerticalAlignment = VerticalAlignment.Stretch;
myStack.Orientation = Orientation.Horizontal;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv1 = new ListViewItem();
lv1.Content = "Test Content";
lv1.Width = 400;
lv1.HorizontalAlignment = HorizontalAlignment.Stretch;
lv1.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv2 = new ListViewItem();
lv2.Content = "Test Content";
lv2.Width = 100;
lv2.HorizontalAlignment = HorizontalAlignment.Stretch;
lv2.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv3 = new ListViewItem();
lv3.Content = "Test Content";
lv3.Width = 100;
lv3.HorizontalAlignment = HorizontalAlignment.Stretch;
lv3.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv4 = new ListViewItem();
lv4.Content = "Test Content";
lv4.Width = 100;
lv4.HorizontalAlignment = HorizontalAlignment.Stretch;
lv4.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv5 = new ListViewItem();
lv5.Content = "Test Content";
lv5.Width = 250;
lv5.HorizontalAlignment = HorizontalAlignment.Stretch;
lv5.VerticalAlignment = VerticalAlignment.Stretch;
// Create new StackPanel "Child" elements with alignment and width
ListViewItem lv6 = new ListViewItem();
lv6.Content = "Test Content";
lv6.Width = 250;
lv6.HorizontalAlignment = HorizontalAlignment.Stretch;
lv6.VerticalAlignment = VerticalAlignment.Stretch;
// Add "Child" elements for the new StackPanel
myStack.Children.Add(lv1);
myStack.Children.Add(lv2);
myStack.Children.Add(lv3);
myStack.Children.Add(lv4);
myStack.Children.Add(lv5);
myStack.Children.Add(lv6);
// Add the new StackPanel as a ListViewItem control
MusicQueue.Items.Insert(1, myStack);
XAML Code:
<ListView Name="MusicQueue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListViewItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal">
<ListViewHeaderItem Width="400">Filename</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Format</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Size</ListViewHeaderItem>
<ListViewHeaderItem Width="100">Duration</ListViewHeaderItem>
<ListViewHeaderItem Width="250">Artist</ListViewHeaderItem>
<ListViewHeaderItem Width="250">Title</ListViewHeaderItem>
</StackPanel>
</ListViewItem>
</ListView>
Of course this is probably not going to be the most efficient way to manually add an item to a ListView stacked horizontally, but it works which is most important :)
If anyone does know a quicker way to do this with less code please let me know :)
Thanks guys
You can use dataGrid in UWP.
But you also can use DataTemplate in ListView, and you can use blow code to solve the width is too small.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
The lib you can use is :https://github.com/MyToolkit/MyToolkit/wiki/DataGrid
And https://liftcodeplay.com/2015/10/24/datagrid-alternatives-in-uwp/
If you can spend money, you can use https://www.syncfusion.com/products/uwp/sfdatagrid
Related
I have a grid which contains dynamically created pairs of textblocks and buttons. I can continue to add these objects infinitely but after they fill the grid, the new pairs are not visible.
I have tried to solve this by putting the grid inside a scrollviewer and each time a new pair is added, increasing the height/maxheight of both the grid and the scrollviewer. But I still cannot see the new elements after the screen is filled.
This is from my .xaml file
<ScrollViewer x:Name="ContentScroll" Grid.Row="1">
<Grid x:Name="ContentPanel" HorizontalAlignment="Left" Height="577" Grid.Row="1" VerticalAlignment="Top" Width="470"> </Grid>
</ScrollViewer>
and this is from my .xaml.cs file
List<TextBlock> textblock_list = new List<TextBlock>();
List<Button> button_list = new List<Button>();
for(int i = 0; i < classlist.Count(); i++)
{
TextBlock tb = new TextBlock();
tb = SetTextBlock(tb, i);
tb.Text = classlist[i].name;
textblock_list.Add(tb);
ContentPanel.Children.Add(textblock_list[i]);
Button bt = new Button();
bt = SetButton(bt, i);
button_list.Add(bt);
ContentPanel.Children.Add(button_list[i]);
Grid.SetColumn(bt, i);
}
Any thoughts on a solution? Thanks in advance.
Try removing the Height="577" from your grid
I have the follow XAML:
<ContentControl HorizontalAlignment="Left" HorizontalContentAlignment="Left" Content="{Binding TotalReviewWordBlock}" Width="465" Margin="5,10,0,5" Foreground="#FF2D2D2D" Background="White"/>
and its binded to the following property:-
public StackPanel TotalReviewWordBlock
{
get
{
StackPanel st = new StackPanel();
st.Orientation = Orientation.Horizontal;
st.Background = new SolidColorBrush(Colors.White);
Paragraph pgf = new Paragraph();
Run r = new Run();
r.Text = App.Convert("Blah ");
r.FontWeight = FontWeights.Bold;
r.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(r);
int Rating = (int)(this.userrating * 2);
string ratingReplacement;
(some more code in the property itself...)
Run run = new Run();
run.Text = " " + this.myText;
run.Foreground = new SolidColorBrush(CommonLib.rgbFromHexString("#FF2D2D2D"));
pgf.Inlines.Add(run);
RichTextBox rtb = new RichTextBox();
rtb.TextWrapping = TextWrapping.Wrap;
rtb.Width = 450;
rtb.Blocks.Add(pgf);
st.Children.Add(rtb);
st.Background = new SolidColorBrush(Colors.White);
return st;
}
}
The problem is when the text is too much(say more that a 1000 character), or the height of the stackpanel is a lot, Its background becomes black. Its as if the stackpanel breaks) I noticed this earlier but at that time it was in a listbox and had multiple items to i simply made the width of each item 480, used blank grids instead of margins and it was "covered". But this time its just one big chunk of text(in a Paragraph). Let me know if you need ay other info. Please help!!
I worked around a similar "black stackpanel" problem by splitting the text into paragraphs to form a List<String>. And then that list of strings would be the ItemsSource of a ListBox.
So instead of a very large StackPanel, I ended up with a long ListBox.
I also prevented user interaction in the ListBox and vertical scroll by using IsHitTestVisible="False" and ScrollViewer.VerticalScrollBarVisibility="Disabled"
So, the ListBoxended up as follows:
<ListBox x:Name="listBox" IsHitTestVisible="False" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="White">
<TextBlock TextWrapping="Wrap" Text="{Binding}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in code behind:
textSplitInParagraphs = new List<String>();
// add paragraphs to the list...
listBox.ItemsSource = textSplitInParagraphs;
Don't know if it is the correct workaround, but I helped me, after some time of banging my head against the table.
Hope this helps.
EDIT: To introduce quickly: WindowsFormsHost added by xaml has all contents. Added by C# has no contents---> pictures below.
When I insert a WindowsFormsHost in the WrapPanel x:Name = "VideoPanel" by the XAML and then add VideoStream videoStream in the .cs file, conents of VideoStream are visible in the that WrapPanel. Everything is OK contents are visible(screenshot below).
Adnotation: VideoStream extends System.Windows.Forms.UserControl
XAML:
<WrapPanel x:Name="VideoPanel" >
<Border BorderBrush="Green" BorderThickness="2">
<WindowsFormsHost x:Name="Host" Width="400" Height="400"></WindowsFormsHost>
</Border>
</WrapPanel>
.cs File:
VideoStream videoStream = new VideoStream();
Host.Child = VideoStream;
Result(correct result):
But when I want to create and insert WindowsFormsHost and the VideoStream in the WrapPanel by C# code there is only border visible with no contents. How to make contents of VideoStream visible?
Code with which I have problem:
WindowsFormsHost formsHost = new WindowsFormsHost();
VideoStream videoStream = new VideoStream();
formsHost.Child = videoStream;
Border lineBorder = new Border();
lineBorder.BorderBrush = Brushes.Green;
lineBorder.BorderThickness = new Thickness(2);
lineBorder.Child = new WindowsFormsHost();
VideoPanel.Children.Add(lineBorder);
videoStream.Height = 400;
videoStream.Width = 400;
lineBorder.Width = 400;
lineBorder.Height = 400;
formsHost.Width = 400;
formsHost.Height = 400;
XAML:
<WrapPanel x:Name="VideoPanel" >
</WrapPanel>
Result(incorrect):
How to make contents of VideoStream visible?
Your problem is on this line :
lineBorder.Child = new WindowsFormsHost();
Should be :
lineBorder.Child = formsHost;
You're creating a new windowsformshost and not using the proper one.
I'd like to create a tabcontrol through code with 2 tabs . I used the code below :
TabControl tb = new TabControl();
tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
tb.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
tb.VerticalContentAlignment = System.Windows.VerticalAlignment.Stretch;
tb.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
ressource_design.initialiserTabControl(tb);
tb.Margin = new Thickness(10, 10, 10, 10);
TabItem ti1 = new TabItem();
ti1.Header = ServicesLangue.RM.GetString("CONTENU_ACCUEIL_LISTE_SAS");
ti1.Content = _listeSAS;
tb.Items.Add(ti1);
TabItem ti2 = new TabItem();
ti2.Header = ServicesLangue.RM.GetString("CONTENU_ACCUEIL_TBSM");
ti2.Content = _tbsm;
tb.Items.Add(ti2);
this.DockPrincipal.Children.Add(tb);
But the height of my tabitem is the height of the children control. This is driving me crazy !
I've tried to add the code below in my child control:
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid}}, Path=ActualHeight}"
But this makes le child control too big !
Note: I have the same problem with the Accordion.
Thanks
Remove any static Height and Width you set in XAML or Code behind.
HorizontalContentAlignment and VerticalContentAlignment are by default set to Stretch.
If your DockPrincipal is a Dockpanel and is filling your whole form, you could set LastChildFill="True"
I am creating Dynamic Rectangle and adding into StackPanel. I need to add text to each rectangle. How can I do that?
A Rectangle doesn't have any child content, so you will need to put both controls inside of another panel, such as a grid:
<Grid>
<Rectangle Stroke="Red" Fill="Blue"/>
<TextBlock>some text</TextBlock>
</Grid>
You can also use a Border control, which will take a single child and draw a rectangle around it:
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock>some text</TextBlock>
</Border>
You say "dynamic rectangle", so it sounds like you are doing this in code. The equivalent C# would look something like this:
var grid = new Grid();
grid.Children.Add(new Rectangle() { Stroke = Brushes.Red, Fill = Brushes.Blue });
grid.Children.Add(new TextBlock() { Text = "some text" });
panel.Children.Add(grid);
// or
panel.Children.Add(new Border()
{
BorderBrush = Brushes.Red,
BorderThickness = new Thickness(1),
Background = Brushes.Blue,
Child = new TextBlock() { Text = "some text" },
});
But if you want a dynamic list of rectangles, you should probably use an ItemsControl:
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1" Background="Blue">
<TextBlock Text="{Binding Text}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you set the DataContext to a list of objects, this XAML will create a Border with a TextBlock for each one with the text set to the Text property on the object.
First of all you can do this, but not by adding the control. And there is a very good reason to do this, for high speed hardware rendering. You can create a special brush from a UI element that caches itself in hardware and fill the rectangle with this hardware, and it is extremely fast. I will just show the code behind because it is the example I have offhand
Rectangle r = new Rectangle();
r.Stroke = Brushes.Blue;
r.StrokeThickness = 5;
r.SetValue(Grid.ColumnProperty, 1);
r.VerticalAlignment = VerticalAlignment.Top;
r.HorizontalAlignment = HorizontalAlignment.Left;
r.Margin = new Thickness(0);
r.Width = 200;
r.Height = 200;
r.RenderTransform = new TranslateTransform(100, 100);
TextBlock TB = new TextBlock();
TB.Text = "Some Text to fill";
// The next two magical lines create a special brush that contains a bitmap
// rendering of the UI element that can then be used like any other brush
// and it's in hardware and is almost the text book example for utilizing
// all hardware rending performances in WPF unleashed 4.5
BitmapCacheBrush bcb = new BitmapCacheBrush(TB);
r.Fill = bcb;
MyCanvas.Children.Add(r);
You need to add a textual control to your StackPanel, such as Label or TextBlock.