In WPF, I have the following:
<ListView.View>
<GridView>
<GridViewColumn
Width="Auto"
DisplayMemberBinding="{Binding SomeProperty, Mode=OneWay}"
Header="Type"/>
The problem is that this only auto-sizes the column to the visible content. This is the same behavior when double clicking the header divider as well.
I want it to resize the column according to all content. For contrast, take the Winforms DataGridView equivalent to the current Auto resizing behavior and the equivalent to the desired behavior:
this.dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; // Current behavior
this.dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // Desired behavior
Is this possible for a WPF ListView?
This question is different than How to autosize and right-align GridViewColumn data in WPF? and others like it because they still trigger the current resizing behavior for visible content and do not address all content.
The problem is the ListView has its ItemsPanel with virtualizing enabled by default. In this mode, only visible content will be rendered and then will trigger the auto-sizing column. So if you don't have many items in your ListView, you can turn off the virtualizing mode via the attached property VirtualizingStackPanel.IsVirtualizing, then it will work expectedly:
<ListView VirtualizingStackPanel.IsVirtualizing="false">
<!-- ... -->
</ListView>
If you don't want to turn off virtualizing, then I don't think there is some easy way to take benefit of the Width="Auto". You may have to implement that feature manually yourself. And technically we need to have knowledge about the largest width to update the column's width accordingly. We can make some for loop every time we need to update the column's width but this is expensive. We can also manage to store the largest width every time a cell has its content changed (this is the better approach). Anyway doing it manually is a pain.
Related
I have a view. The grid inside the view is divided into 2 columns.
<Grid x:Name="grdView">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
Inside the Auto column(Column 0), I have another view
<Border Grid.Column="0" Style="{DynamicResource BorderStyle}">
<Views:ViewerDataBrowser x:Name="dataBrowser" DataContext="{Binding ViewDataBrowserInstance}" />
</Border>
Inside this view I have a listbox and a data template defined for the list box.
Inside the data template I have 2 rows and 2 textblocks in each of them.
Issue
When the textblock characters are more than the width of the column, the listbox is being stretched and a scroll bar is also displayed. I don't want that to happen. I want the text to be truncated and show ... at the end.
I tried text trimming and text wrapping for the textblock. But it did not work. I also tried to set the width of data template to Auto, but it is not working. The only possible solution working for me is to set the width of the data template to a constant value.
I want the listbox to fit inside the grid and not show the scroll bar even though the text block have lengthy text. Please suggest a solution.
You can get and set the horiztonalScrollBar property of a listBox as described on the MSDN site. When setting the width of the listBox (pre-uwp) you may use device independent pixels (DIPs). Also, instead of using a constant, you may set the width proportional to that of the listBox's container--though not recommended vs DIPs and auto-resizing since certain dimensions behave better.
The issue is caused since the column width of the grid was set to "*".
When I changed the column width to constant, ie the same width as that of the parent, the issue seems to be fixed.
Regarding the truncation of the textblock, I set the textbox trimming property.
I need some help confirming I'm seeing a bug.
I am creating a "TagCloud" in xaml for metro. Nothing complex, it should be simple.
I create TextBlock objects in the code behind and then add them to the children of a VariableSizedWrapGrid
Each TextBlock is a different height and width - and this is determined by the testblock.Measure(size), then setting the width and height via DesiredSize.Width and DesiredSize.Height
testblock.Measure(new Size(10000, 250));
dWidth = Double.Parse(testblock.DesiredSize.Width.ToString());
dHeight = Double.Parse(testblock.DesiredSize.Height.ToString());
The problem is, when the TextBlock objects are added they basically clip, they all lock to one single size (basically the behavior of a WrapGrid). Essentially the VariableSizedWrapGrid is refusing to allow variable heights and widths within its child elements? I have no idea why it clips everything.
<VariableSizedWrapGrid x:Name="vswg" Orientation="Horizontal" Width="Auto" Height="200" Grid.Column="1"/>
IEnumerable<TextBlock> textBlocks =
(from cloudItem in cloudItems
select ConvertToTextBlock(cloudItem, fontWeight));
vswg.Children.Clear();
foreach (TextBlock t in textBlocks)
{
vswg.Children.Add(t);
}
The ConvertToTextBlock() returns a new TextBlock with a different text and FontSize
I cannot get the VariableSizedWrapGrid to actually have a "variable sized" child control. Perhaps I am just using this all wrong?
Try Something like this:
<GroupStyle.Panel> <ItemsPanelTemplate > <VariableSizedWrapGrid x:Name="MyGrid" Orientation="Horizontal" MaximumRowsOrColumns="7"
ItemWidth="{Binding DataContext.ItemTemplateWidth, ElementName=pageRoot}"
ItemHeight="{Binding DataContext.ItemTemplateHeight, ElementName=pageRoot}"
></VariableSizedWrapGrid> </ItemsPanelTemplate> </GroupStyle.Panel>
Also consider reading:
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2012/09/14/windows-8-xaml-and-displaying-multiple-sized-items.aspx
http://www.acnenomor.com/3756161p1/how-to-display-gridview-items-with-variable-width-in-window-8
Try considering using DataTemplate.
VariableSizedWrapGrid provid ItemHeight and ItemWidth properties. Then, you can only choose the Width and Height of an item "in cells". So, you can choose your item to fit 3 cells width and 1 cell height.
You should consider reading: http://blogs.u2u.be/diederik/post/2012/03/07/Databinding-to-the-VariableSizedWrapGrid-in-Windows-8-Metro.aspx
Change this:
DesiredSize.Width.ToString()
To this:
Width.ToString()
The layout system is a complex three pass process, when you allow the "DesiredSize" value to be controlled by saying "DesiredSize in the code" the layout system takes charge. When you specify a width the layout system is overridden.
I'm trying to figure out if there is a way to dynamically add controls into another control (I know this is a bit vague...). My program is in C# 4.0, and WPF. Basically, I'm trying to create a datagrid but as opposed to having normal type 'cells' (ie text, hyperlink etc), I need each cell to hold a number of items. I figured that this wasn't possible in the datagrid, so I'm trying to do the following: Using a stack panel, add a variable number of wrap panels. Each wrap panel will contain 7 grids, where each grid will hold the data I want (I'll likely use some user control in place of the grid I think...)
An example of the code I have so far...
<StackPanel Height="559" HorizontalAlignment="Left" Margin="24,11,0,0" Name="tyStackPanel" VerticalAlignment="Top" Width="783">
<WrapPanel Height="100">
<Grid Width="100" Height="100">
</Grid>
</WrapPanel>
<WrapPanel Height="100">
</WrapPanel>
</StackPanel>
Is there a way to create a variable number of Wrap Panels though? (ie like you would have a variable number of rows in a datagrid)
Any help and suggestions is much appreciated!
P.S. Figure I should explain what I'm trying to achieve a bit better. I have a collection of items, each with 5 properties that I want displayed together. These items are grouped by Name (like a row in a data column) and a column header (which is not one of the 5 properties). I want to group the collection by (Name, ColumnHeader) pairs, and then in each "cell" display those 5 properties. In the way I'm trying to set it up above, there would be a WrapPanel per 'Name' and a Cell/Grid contained in it for each ColumnHeader.
WPF supports this very well with the ItemsControl and its various derived controls, one of which is the DataGrid, which actually does support the scenario you're looking for.
Basically, when you use an ItemsControl, DataGrid or one of these item controls, you bind the ItemsSource to whatever property holds your data items, and define the DataTemplates for each item, which can be any arbitrarily-complex block of XAML. For DataGrid, you can swap a normal column for a DataGridTemplateColumn, which can, again, be as complex as you want.
Check out the Data Templating Overview for, well, an overview.
I have a problem using C# and WPF of binding Text to TextBoxes in a Grid. The binding actually works, except that it doesn't show up on the UI until I double click in the TextBox to edit. Then the text fills in. I'm using DataGridTemplateColumn.CellEditingTemplate. I've noticed that if I just use CellTemplate, the data fills in (but obviously I can't change it). Can anyone tell me what must be different? I'll post code if needed.
If you simply want to bind a text column then you can do this.
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
If you have something more complicated in mind with a DataGridTemplateColumn, then you may need a to specify a CellTemplate and a CellEditingTemplate. You'll need to describe what your trying to do, and show the Xaml.
I've got a DataGrid in a Silverlight application with data in it. There's also a button on our app that can change the layout such that the DataGrid changes width.
The problem is when you are in the "small" mode and scroll around, for columns that you can't see, their DataGridCell elements get Visibility=Collapsed. Now this is fine when you are scrolling around, but when the size of the DataGrid increases to show all columns, they stay collapsed. However for some reason you can always see all the cells in the first row.
This smells like a bug in the DataGrid control. Does anyone know a way to work around it? I've got as far as adding a handler for SizeChanged on the DataGrid, but I'm not quite sure what to call to force it to show those collapsed cells.
EDIT: After some testing I've found that it only happens with GridLinesVisibility="Horizontal"
XAML (Clicking toggles width of DataGrid from half to full):
<StackPanel Orientation="Vertical">
<data:DataGrid x:Name="testDataGrid" GridLinesVisibility="Horizontal" />
<Button HorizontalAlignment="Center" Content="Switch Width" Name="switchWidthButton" Click="Button_Click" />
</StackPanel>
Update: Though it can still happen sometimes with GridLinesVisibilty not set. I have not worked out exactly what circumstances this happens under.
After some discussion on the MS alias I've found that it is in fact a bug in the DataGrid. I've sent them a repro project so hopefully it will be fixed in the future. In the meantime as a workaround, you can hide and re-show one of the columns when the DataGrid changes size:
<data:DataGrid x:Name="testDataGrid" GridLinesVisibility="Horizontal" Width="150" SizeChanged="testDataGrid_SizeChanged" />
-
private void testDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
this.testDataGrid.Columns[0].Visibility = Visibility.Collapsed;
this.testDataGrid.Columns[0].Visibility = Visibility.Visible;
}