How can limit the height of a grid row in wpf - wpf

I'm developing an Outlook Add-in in WPF. Outlook Add-in is an UserControl. My simplified XAML code look's :
<UserControl>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0">Header</TextBlock>
<ListBox Grid.Row="1"></ListBox>
<Button Grid.Row="2"></Button>
</Grid>
</UserControl>
The list box items are loaded dynamically. With the help of this class that I founded here http://www.codeproject.com/KB/WPF/GridLengthAnimation.aspx the height of the 3rd row is set to 0.4* when the button is pressed.
The problem is that when I have more items in the list box the second row expands and the 3rd row disappears.The solution could be if I set the MaxHeight of the second row to 100% height-170, but I don't know the available height for the UserControl.
Any ideas?

Instead of specifying Height try specifying MinHeight for the 3rd row, that way it won't shrink beyond a certain size.

The problem was here ( on the library that I've used )
public override object GetCurrentValue(object defaultOriginValue,
object defaultDestinationValue, AnimationClock animationClock)
{
double fromVal = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value;
double toVal = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value;
if (fromVal > toVal)
{
return new GridLength((1 - animationClock.CurrentProgress.Value) * (fromVal - toVal) + toVal, GridUnitType.Pixel);
}
else
return new GridLength(animationClock.CurrentProgress.Value * (toVal - fromVal) + fromVal, GridUnitType.Pixel);
}
I've replaced GridUnitType.Star with GridUnitType.Pixel. And now it work's perfectly

Related

take image of full datagrid

I have:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<sdk:DataGrid Grid.Row="0" ...>
...
</sdk:DataGrid>
</Grid>
Note there is no Height="Auto" in row definition so that datagrid takes all height.
I'm trying to make a picture of full datagrid (include invisible space that needs scrolling). I tried:
ImageExtensions.ToImage(myDataGrid);
also
var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
where pixelHeight was obtained either using SizeChanged event or DesiredSize property.
All in vain. Height was always the height of screen. If I used auto="height" in row definition then it would work, but datagrid wouldn't take all space / or no scroller when it's too large.
Anyone managed to get it work?
A workaround:
GridLength h = grid.RowDefinitions[0].Height;
grid.RowDefinitions[0].Height = GridLength.Auto;
grid.UpdateLayout();
try
{
var writeableBitmap = new WriteableBitmap((int)myDataGrid.ActualWidth, (int)myDataGrid.ActualHeight);
}
finally
{
grid.RowDefinitions[0].Height = h;
grid.UpdateLayout();
}

Prevent WPF ListView or ListBox from showing "half" Items

in our application we have some ListViews and ListBoxes inside grids where you can change the actual height of the control with help of a grid splitter.
When doing so you are able to arrange the height of the ListBox so one of the items is not fully visible because the ListView becomes to short to display it.
This is a behavior we don't want.
From my research so far it seems there is not way the prevent a ListBox or ListView from showing partial items but maybe someone found another way to deal with this problem. Maybe the item can trigger itself invisible when it is only half visible. But how can we find out?
We are open to any suggestions.
There's no way I know of to fix a ListView this way. For ListBox, though, you can override ArrangeOverride and arrange the items yourself. Stack the items you want to see, and arrange the items you do not wish to be visible (e.g., partially visible items) so that they are not visible. For example, a non-virtualized version:
/// <summary>
/// Used to arrange all of the child items for the layout.
/// Determines position for each child.
/// </summary>
/// <param name="finalSize">Parent passes this size in</param>
/// <returns>Parent size (always uses all of the allowed area)</returns>
protected override Size ArrangeOverride(Size finalSize)
{
// Arrange in a stack
double curX = 0;
double curY = 0;
foreach (UIElement child in InternalChildren)
{
double nextY = curY + child.DesiredSize.Height;
if (nextY > finalSize.Height) // Don't display partial items
child.Arrange(new Rect());
else
child.Arrange(new Rect(curX, curY, child.DesiredSize.Width, child.DesiredSize.Height);
curY = nextY;
}
return finalSize;
}
You just have to set MinHeight or MinWidth to the cell which you'r resizing. Try this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="50"/>
<RowDefinition Height="Auto"/>
<RowDefinition MinHeight="50"/>
</Grid.RowDefinitions>
<ListBox HorizontalAlignment="Center" Margin="10">
<ListBoxItem>First</ListBoxItem>
<ListBoxItem>Second</ListBoxItem>
<ListBoxItem>Third</ListBoxItem>
<ListBoxItem>Fourth</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<ListView Grid.Row="2" Margin="4">
<ListViewItem>First</ListViewItem>
<ListViewItem>Second</ListViewItem>
<ListViewItem>Third</ListViewItem>
<ListViewItem>Fourth</ListViewItem>
</ListView>
</Grid>

W7P ListBox doesn't stay scrolled in the emulator

I have a ListBox in a xaml page for a Windows Phone 7 app. It starts out empty, then I populate it with some items once they are retrieved from a web service. So far that all works fine - the items show up in the list and all seems fine. The problem I have is when I try to drag the list to scroll to the bottom (in the emulator): I can scroll down, but as soon as I release the mouse button the list springs back to the top as though I hadn't scrolled it at all. Any insights into why it would behave this way?
<Grid x:Name="ContentPanel" Grid.Row="2" Margin="0,0,0,0" Canvas.ZIndex="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <!-- EDIT: the problem was "Auto" here should have been "*" -->
</Grid.RowDefinitions>
<!-- removed other element for brevity -->
<ListBox Name="InfoBoardListBox" Grid.Row="1" SelectionChanged="InfoBoardListBox_SelectionChanged"
Margin="0,0,0,0" FontSize="26.667" />
</Grid>
And the method that populates the list:
foreach (InfoBoard entry in boards.Values) {
item = new ListBoxItem();
item.Content = entry.Name;
item.Name = entry.Id.ToString(); //used to tell which entry was clicked
InfoBoardListBox.Items.Add(item);
}
Try setting the Height of the second row to * instead of Auto; I think it's to do with the size that the ListBox thinks it is vs. the available space.

Detect which element scrollbars belong to

I have a relatively complex layout. It consists of:
A grid with one column and three rows.
In the first row (the on giving me trouble) I have a developer express componenet - another GridControl.
My problem is, that though the height of this first row is Auto, the vertical scrollbar displays even though there's space enough for content.
I've tried setting the ScrollViewer.VerticalScrollBarVisibility="Hidden" on the row's rowdefinition, but this doesn't help.
Likewise, I've set the inner GridControl to not use scrollbars (using some Developer Express magic - not just ScrollViewer as this doesn't work)
Yet, no matter what I do, that damn scrollbar appears... Is there any way to figure out which control renders it, so I can disable the damn thing? It's not just a question of it being ugly - scrolling it actually messes with the layout!
Thanks in advance!
The relevant code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" ScrollViewer.VerticalScrollBarVisibility="Hidden" />
<RowDefinition Height="*" MaxHeight="240" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<dxg:GridControl Name="StudySizeGrid" Grid.Column="0" Grid.Row="0" >
<dxg:GridControl.Resources>
<ControlTemplate x:Key="{dxgt:TableViewThemeKey ResourceKey=ControlTemplate}">
<ScrollViewer x:Name="scr"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"
Focusable="False"
dxg:GridControl.CurrentView="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Template="{DynamicResource {dxgt:TableViewThemeKey ResourceKey=ScrollViewerTemplate}}">
<ScrollViewer.CanContentScroll>False</ScrollViewer.CanContentScroll>
</ScrollViewer>
</ControlTemplate>
</dxg:GridControl.Resources>
...
</dxg:GridControl>
EDIT FOR CLARIFICATION: This is WPF issue :-)
You could try checking out the VisualTree, i think Snoop might be helpful for that, it probably has some other useful features too. Getting the VisualTree is a trivial matter though, you can write a single recursive method using the VisualTreeHelper, so you might not need the big guns.
e.g.
public static TreeViewItem GetVisualTree(this DependencyObject dpo)
{
TreeViewItem item = new TreeViewItem();
item.Header = dpo.GetType().ToString().Split('.').Last();
if (dpo is FrameworkElement && (dpo as FrameworkElement).Name != string.Empty) item.Header += " (" + (dpo as FrameworkElement).Name + ")";
int cCount = VisualTreeHelper.GetChildrenCount(dpo);
for (int i = 0; i < cCount; i++)
{
item.Items.Add(VisualTreeHelper.GetChild(dpo, i).GetVisualTree());
}
return item;
}
Wrote that quite some time ago, it's very sketchy (wouldn't recommend making it an extension method), gets the whole tree at one, could be modified to only fetch children on expansion of the node.
You could use something like Google Chrome's tools.
I would, in Chrome, right click around the area that has the scroll bars and select "Inspect Element". Chrome will highlight with a border what element you are looking at. You can then navigate the html within Google Chrome's inspector until it is highlighting the element with the scrollbar.
You can then find the reason from there.

how can i add a row dynamically in 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.

Resources