WPF: ColumnSpan in UniformGrid - wpf

I know that UniformGrid haven't attached properties ColumnSpan and RowSpan. But what i really need is container with fixed width and inner cells also with fixed widths, except few UIElements, that should be filled in few cells.
For example:
<UniformGrid Columns="4"> <TextBlock>1</TextBlock>
<TextBlock>2</TextBlock>
<TextBlock Grid.ColumnSpan="2">34</TextBlock>
UniformGrid is ideal for me except this situation: last TextBlock is not fill two cells.
Is it possible use some other solution to give the needed result?
Thank you for any advise!
P.S.And... why XAML parser is not stops with error where process this markup?

You could use a Grid with the columns having varying * widths:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBlock>1</TextBlock>
<TextBlock Grid.Column="1">2</TextBlock>
<TextBlock Grid.Column="2">34</TextBlock>
</Grid>

I wanted use only XAML, but for now I still not found the answer. So, i've used following solution: placed all my elements in horizontal WrapPanel and set width for each element in code.

Related

Vertical gridlines in a ListView

I've got a WPF ListView that I'm using as a GridView. Is there any way I can get vertical gridlines in there?
The ListView has a MinHeight specified, so I'd like the GridLine to go all the way to the bottom of the grid, so it'll fill the empty space.
This seems to be a rather tricky problem. Is is possible to solve?
This is how I do it.
<ListView Grid.IsSharedSizeScope="True"
ItemsSource="{Binding Path=MyList,FallbackValue='12345'}" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" SharedSizeGroup="col0"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*" SharedSizeGroup="col2"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="10,0"
Text="{Binding Path=Name, FallbackValue='Name goes here'}"/>
<Border Grid.Column="1" Margin="0,-2"
BorderBrush="DarkGray"
BorderThickness="0,0,1,0" />
<TextBlock Grid.Column="2" Margin="10,0"
Text="{Binding Path=DateModified, FallbackValue='Date goes here'}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The SharedSizeGroup and Grid.IsSharedSizeScope properties are key to this way of doing it. The Margin="0,-2" property on the Border makes sure the dividing line looks like a continuous vertical line. If you add vertical margin to the two textblocks, you will need to increase the negative vertical margin of the border.
This will take care of lining things up into two uniformly sized columns with a vertical line between them, but it won't extend into areas where there is no data. A ListView might not be the best option if you want that functionality.
Adding some data to the MyList property in the ViewModel gives this as a result:
Of course, the MyList property needs to be a list or collection of a class that has Name and DateModified as properties.

How to automatically collapse a Grid Column in xaml?

Basically I'm getting some data from a service and displaying the results in a listbox. The template for the items is using a grid. NOTE: If there is a better way let me know.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0"/>
<TextBlock Grid.Column="1"/>
</Grid>
The problem is, that sometimes an image is not returned. In that case the column for the image should collapse and the text column should take up the full width.
I've tried a couple of different ways already with no luck. How can I collapse this column when no image is returned?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0"/>
<TextBlock Grid.Column="1"/>
</Grid>
Setting the image column width to auto will resize the column width according to the image size. If there is no image the size will be set to 0. The text column is set to *, this way it always takes all the available space.
Note: If your images are big, you may need to set MaxWidth as well.
You can use Expander control and set IsExpanded property.

Give a WPF Grid the width of a ScrollViewer minus the scrollbar

I have a WPF UserControl with two Grids above each other. The bottom Grid is in a ScrollViewer. The idea is to have the first Grid be the header of the second Grid. I'm having trouble with the width of the columns however. Both Grids should take up all the space they can (the width of the Window), but the top Grid should of course be a little less wide, because there's a scrollbar on the right of the bottom Grid.
This is the simplified Xaml I've got:
<UserControl>
<DockPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<ScrollViewer>
<Grid>
<Grid.ColumnDefintions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefintions>
</Grid>
</ScrollViewer>
</DockPanel>
</UserControl>
This renders fine actually, except that the most right column of the top Grid extends over the scrollbar, which I want to avoid.!
Here is an image of the result: Grid column and width of scrollbar. The red indicates where the column/cell is now, but I want it to stop at the blue line. I've tried SharedSizeGroups, but that seems to make my Grids small again (not take up the full space of the window).
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Name="sv">
<Grid MinWidth="{Binding ElementName=sv, Path=ViewportWidth}" MinHeight="{Binding ElementName=sv, Path=ViewportHeight}" />
</ScrollViewer>
The problem is setting up a correct dependency between the ScrollViewer container size and the grid size. Let us consider just the width: the binding above allows the ScrollViewer to expose the horizontal scrollbar only if necessary:
enlarging a single column of the grid (eg. with a splitter) does not provoke the resizing of the other columns (which would happen if you bind Width instead MinWidth).
Using the ViewportWidth instead of ActualWidth takes into account the scrollbar width, if there is one.
Just try
Found the solution here. I gave my top Grid a Width:
Width="{Binding ElementName=BottomGrid, Path=ActualWidth}"

WPF separator between grid buttons

I have a grid with 4 buttons...1 row, 4 columns. I am looking for a way to visually group the two buttons on the left from the two on the right. I was looking for a way to do this with a separator but it doesnt seem to be playing nice with Grid, preferring StackPanel.
Is this the right control?
If so, how does one make the thing separate the columns (populated with buttons in this case)?
Thanks.
In case anyone else stumbles across this, easiest solution:
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
Have you tried a GridSplitter?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Height="*" />
<ColumnDefinition Height="Auto" />
<ColumnDefinition Height="100" />
<ColumnDefinition Height="100" />
</Grid.ColumnDefinitions>
<Button/>
<Button/>
<GridSplitter ResizeDirection="Columns" Grid.Column="2" Height="Auto" Width="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/>
<Button/>
</Grid>
I usually use the simple choice to add a column with a fixed width between the buttons
You can actually use a different background color or insert an image
You can use Separator if you style it correctly. By default it creates a horizontal line. You have to apply different styling to make it vertical.
See this post for how to style it as a vertical line in a WPF Grid:
CodeProject discussion
The discussion also mentions that StatusBar applies some styling to Separator elements, as long as you don't wrap them in StatusBarItems. Perhaps StackPanel does something similar.

WPF Data Binding - Bind to UI Control from a Template

I have a template in my section. I want to bind the Width of one of the values in that template to the width of a control in my Main XAML section.
Can this be done? Expression Blend only shows the Template in the Binding list.
For example, this is what I am wanting to have work:
<Windows.Resources>
... My template stuff
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="{Binding ElementName=SecondColumn, Path=Width}"/>
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
... More template stuff
</Windwos.Resources>
<Grid Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="FirstColumn" Width=".25*" />
<ColumnDefinition Name="SecondColumn" Width=".5*" />
<ColumnDefinition Name="ThirdColumn" Width=".25*" />
</Grid.ColumnDefinitions>
... Rest of my XAML
Once inside the Template you're sort of isolated from other elements (with good reason - it can be reused elsewhere). In this case (assuming the template is used somewhere under "MainGrid") it looks like you can use a RelativeSource FindAncestor Binding to locate the parent Grid (you'll need to make sure to count the Grids in the VisualTree to get the right AncestorLevel - in just the code here it would be 2). The Path would be ColumnDefinitions[1].Width. Keep in mind that this depends on you maintaining the structure of the elements where you are using the template so it is a bit fragile. There is also an alternate method using SharedSizeGroup that can connect Grid Rows or Columns at different levels but that works only with Auto and fixed pixel sizes. This Binding method works with fixed and * sizes.
Entire Binding:
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}, AncestorLevel=2}, Path=ColumnDefinitions[1].Width}"
Do you mean that you want your columns to be always the same width or do you mean that at first, they are at same width? If so, why not define a style and use it from both columns?

Resources