how can i add a row dynamically in WPF? - wpf

I need to create a row in XAML which has a label,two radio buttons.. Based on some operation i need these row to be visible..else i need it to hidden.. I do not want the empty space to be displayed.. Is this possible only through code? If so can anyone help me out please?

Place the row in a grid and set it's height set to 'Auto'. Place your controls in a grid (or other container) and set it's Visibility to Collapsed for not visible and Visible for when you need to show it.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
...
<RowDefinition Height="Auto" /> <!-- Your 'hidden' row -->
...
</Grid.RowDefinitions>
<!-- your collapse content -->
<Grid Grid.Row="2" Visible="Collapsed" x:Name="hiddenRow">
....your controls...
</Grid>
</Grid>
Then to show the controls...
hiddenRow.Visible= Visibility.Visible;
Hope that helps....

What do you mean by "row"? A DataGridRow? An item in a vertical StackPanel?
Is this row part of a DataTemplate for an item?
Without knowing more, it's hard to say.
But basically, you can bind some value trough a ValueConverter to the UIElement.Visibility property if what you want is to hide/show any UiElement.

Related

wpf grid with automatic number of rows

I am aware that I can use Grid.Rowdefinitions to define the number of rows and their properties on a WPF Grid control.
However is there a way to set the grid to automatically grow/add rows as controls are added, without having to explicitly state it?
However is there a way to set the grid to automatically grow/add rows as controls are added, without having to explicitly state it?
No, there isn't. Depending on your requirements, you probably want to replace the Grid with another Panel like for example a StackPanel or a UniformGrid with a single column:
<UniformGrid x:Name="grid" Columns="1" />
Then you don't need to care about setting any Grid.Row property.
You can do that in your code behind.
Define following in the .xaml of your window:
<Grid x:Name="YourGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
</Grid>
Now use a loop to create as many rows as you need:
foreach(Control control in controlls)
{
YourGrid.RowDefinitions.Add(new RowDefinition());
YourGrid.Children.Add(control);
Grid.SetRow(control , YourGrid.RowDefinitions.Count - 1);
}
If you have a lot of controls this could help you. It will add the control automatically into the created row.
If you don't want to add the controls and rows in the code behind, you will have to add the rows manually. As far as I know there is no way to automate it.

WPF control alignment is wrong when dynamically added

Hi I thought I could solve this easily but it is driving me crazy.
I am using a UserControl to house a video player control based on VLC, along with play and stop buttons etc. I then place the UserControl on my main form. if the UserControl is declared in XAML it behaves normally.
I decided to rewrite the code to instantiate my UserControl dynamically, in case I need to destroy it and create another on the fly. But when I do the video moves to the top of its container instead of the middle.
The UserControl relevant section is here:
<Grid x:Name="LayoutParent" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="12" />
</Grid.RowDefinitions>
<!-- I comment this if adding player dynamically -->
<!--<wpf:VlcPlayer Grid.Row="0" x:Name="Player" />-->
<!-- I un-comment this if adding player dynamically -->
<Grid x:Name="VideoPlayerPanel" Grid.Row="0" Margin="0" />
<StackPanel Grid.Row="1" Opacity="0.8">
...(buttons etc)
</StackPanel>
<ProgressBar ...(progressBar etc) />
</Grid>
My codebehind looks like this:
Dim Player As VlcPlayer = New VlcPlayer ' uncomment If adding the player dynamically
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Player.SetValue(Canvas.ZIndexProperty, -1)
VideoPlayerPanel.Children.Add(Player)
VolumeSlider.Value = 50
End Sub
I have tried VerticalAlignment="Center" and VerticalAlignment="Stretch" in XAML on the VideoPlayerPanel, with Center the video disappears entirely, with Stretch it still aligns to the top.
Any thoughts as to what I might do to align this centrally would be much appreciated!
When adding Player dynamiccaly you have different result, because you wrap Play in additional Grid. Try to add Player directly to first row of LayoutParent:
Player.SetValue(Grid.Row, 0)
LayoutParent.Children.Add(Player)
Thanks to all that replied.
I did some more research, I substituted in a Rectangle for the player control and it aligned perfectly. That led me to discover that the third party control was itself at fault. I had to get the source and change the VerticalAlignment directly.
Sorry for the runaround.
Remove Height="*" from first Row . * is used to occupy remaining space, so it is good to use it for the last Row.
Use fixed width and or Auto.

Difference between GridView and Grid

Can anyone tell me the difference between GridView and a Grid in WPF XAML?
Here are the details for UWP. Should be similar for WPF I think.
Grid - used for defining layouts and formatting or static information. It is one of the several "layout panels" that are available (others include: RelativePanel, StackPanel, VariableSizedWrapGrid, and Canvas). Grid does not have an ItemSource member to dynamically display items by binding. Grid does have Grid.Row and Grid.Column attached properties (i.e. that can be used on other controls) to position them within the Grid.
Sample Code:
<Grid x:Name="LayoutPanel1" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Margin="20"
BorderBrush="{StaticResource Page_Brush}"
BorderThickness="1 1 1 1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="44"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
More Information: Grid Class, Layout Panels
GridView - used for displaying a set or collection of data (i.e. dynamic number of items). Another control available to display a set or collection of data is a ListView. One way to use this is by setting ItemSource (i.e. binding). By default, a data item is displayed in the GridView as the string representation of the data object it's bound to. To specify exactly how items in the GridView are displayed, you create a DataTemplate to define the layout of controls used to display an individual item. The controls in the layout can be bound to properties of a data object, or have content defined inline. You assign the DataTemplate to the ItemTemplate property of the GridView. The DataTemplate can contain a Grid (or any of the other layout panels mentioned above) to specify the layout of controls of an individual item.
Sample Code:
<GridView ItemsSource="{x:Bind MyItems}"
IsItemClickEnabled="True"
ItemClick="GridView_ItemClick"
ItemTemplate="{StaticResource MyItemTemplate}"
BorderBrush="{StaticResource MyItemBrush}"
BorderThickness="1 1 1 1"
HorizontalAlignment="Stretch"
/>
More Information: GridView Class, List view and Grid view, Guidelines for list view and grid view
A simple explanation would be
Grid
If you have just a single item with no repetitive subitem design then a grid is used. If the number of subitems are fixed
GridView
If you have a repetitive design like collection and you dont know the number of items that can be present then a gridview is used instead.
You can find more details on msdn forums.
From what I see Grid is more like a table, each row contains the same number of items (one for each column) no matter the size of the window.
GridView looks like a table but if you reduce the width of the window, the items from one row will jump on the next row:

WPF resize issues when using RowDefinition Height="*" in Grid

UPDATE I added the UserControl definition to the XAML.
I've noticed some strange behavior in a couple of WPF applications I've created lately, that seem to be related to using "*" for a Grid row height or column width.
The behavior I'm referring to is when trying to expand items in a control (like a treeview), the entire window will resize its height instead of creating a scrollbar. So if I just run the application, and start expanding nodes, when the items extend beyond the visible portion of the UI then the window will resize.
BUT if I resize the window first, or even just click on the bottom or right border (without actually resizing), then it will behave normally and leave the window height alone, with a scrollbar on the treeview.
<UserControl x:Class="ProjectZ.Views.GenericDefinitionView"
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"
xmlns:cal="http://www.caliburnproject.org"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:local="clr-namespace:ProjectZ"
xmlns:behaviors="clr-namespace:ProjectZ.Behaviors"
mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Menu Grid.Row="0" Name="mnuMainMenu" IsMainMenu="True">
... menu stuff
</Menu>
<xcad:DockingManager ... />
</Grid>
</UserControl>
I've played around with it and it seems to always start happening after I've used the "*" value for a grid row height or a column width. If I take that out, it seems to behave normally.
Has anyone else run into this? Any ideas what I'm doing wrong or could do differently to fix this? The only other information I think might be relevant is that this is using Caliburn.Micro. The only settings passed to the window when launching are: MinHeight, MinWidth, Title, and Icon.
The problem is that you never specify a height in the visual tree above the element.
Your UserControl or the Window that's created needs a specific height if you want to use star sizing effectively. Otherwise, a height is "chosen" at runtime, but the Window is effectively set to size by content. As you change items, the Window resizes.
As soon as you touch a border, the Height is being set (whether or not you resize), in which case it then dictates the layout correctly.
If you specify a default height for the Window as its created, the issue will likely resolve itself.
The resizing must be caused by the code:
<UserControl
//...stuff>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
</UserControl>
Where the < * > can be understood as "Take the rest of all available space, after placing all the other elements first". So when you add another element in the control the view will set itself and the the
<RowDefinition Height="*" />
Will resize itself acordingly to take the remainder of space available. To remove this you can just set a specific height for the row or another idea will be to add another Grid inside the row definition so that it won't resize since it will always be inside the row, but still have all of it's functionality.

WPF ListView Always focused last added item?

I have many ListViews with the same DataSource with IsSynchronizedWithCurrentItem="True"
and I'm dynamicaly adding items to this DataSource.
The problem ist when the scrolls appears, the added items are not visible unless I move the scrollbar. Should I use another Control for this purpose.. or how can bring the last added item into view (and scrollbars).
Until now I was doing everything directly in XAML, so I'd appreciate such a solution if possible.
if ( !(myListView.Items.IsEmpty) )
{
myListView.ScrollIntoView(myListView.Items[myListView.Items.Count - 1]);
}
Hope that helps!
I think you may need to use the method:
ListView.ScrollIntoView(ListView.SelectedItem);
I come with a solution:
It cannot be applied in all cases, but it this one it's sufficient!
The trick is to
disable the ListView ScrollBars and surround it with the ScrollViewer.
...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" /> <!-- This is needed! -->
...
</Grid.RowDefinitions>
..
<ScrollViewer x:Name="MyScrollViewer" Grid.Row="0" >
<ListView Name="MyListView"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
ScrollViewer.VerticalScrollBarVisibility="Disabled" />
</ScrollViewer>
...
</Grid>
Then simply if needed call
MyScrollViewer.ScrollToEnd();
That sounds suspicious, but even if it's true, you can always call ListView.BringIntoView() method, to... bring selected item into view :).

Resources