I have run into a bizarre problem. I am displaying a UserControl within a UserControl and at the moment each contains a completely identical ListView, as in I copied and pasted it from one to the other. On the parent UserControl, the ListView displays properly, but on the sub-UserControl (whatever it's called), the ListView columns refuse to stretch to fit their content. I have no idea why this is happening since the code of both ListViews is exactly the same. Both are placed directly on the grid.
On the top left is the ListView from the parent control and on the bottom right is that of the child control. Here is the code for both ListViews:
<ListView ItemsSource="{Binding Adventurers}"
Name="AdvListView"
HorizontalAlignment="Stretch"
Grid.Column="2"
Grid.ColumnSpan="1"
Grid.Row="2"
ScrollViewer.CanContentScroll="False"
BorderThickness="3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding ShowAdvWindowCommand}"
CommandParameter="{Binding ElementName=AdvListView, Path=SelectedItem}"
PassEventArgsToCommand="False" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.Resources>
<DataTemplate x:Key="NameTemplate">
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Name}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
</DataTemplate>
<DataTemplate x:Key="StatusTemplate">
<TextBlock Margin="2,1,1,1" Text="{Binding Status}" VerticalAlignment="Center" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" CellTemplate="{StaticResource NameTemplate}" />
<GridViewColumn Header="Status" CellTemplate="{StaticResource StatusTemplate}" />
</GridView>
</ListView.View>
</ListView>
Why would this work on one and not the other? I'm really at a loss at this point.
Update: In the parent UserControl, the grid layout is:
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
//Listview here among other controls
</Grid>
In the child:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
//Listview here
</Grid>
Modifying Grid.Row, Grid.Column, RowSpan, or ColumnSpan to be correct doesn't fix the problem.
Update: A bit more info that may be relevant: When I try to use Snoop on my program. I get this error:
"BindingFailure was detected - The assembly with display name 'Snoop.XmlSerializers' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'Snoop.XmlSerializers, Version=2.8.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Snoop has no problem with other programs. I don't know if this is related to the issue at all, but I figured I'd post it anyways.
Update: I don't think this would matter, but just to be thorough, here is where the child UserControl is created within the parent:
<Grid>
//Other controls
<UserControl Grid.Column="3"
Grid.Row="3"
Visibility="{Binding AdventurerInfoVisibility}">
<view:AdventurerInfoView />
</UserControl>
</Grid>
At this point I'm completely stumped. I can create a copy of the ListView in the parent UserControl and have it display properly... but for some reason it doesn't want to behave in the child UserControl... I'm open to any ideas and if you need more code I would be more than happy to provide it.
After much tinkering and frustration, I found out what was causing the problem. The child UserControl's Visibility was set to Collapsed by default and was made visible by a button click. When I made it visible by default, the columns stretched properly.
Now I just need to find out how to allow it to start collapsed and still maintain the stretched column width.
I create a deom use your code, and it does not to repeat your problem.
I think maybe your child usercontrol had some TextBlock style, and override your container setting.
Related
I have a ListView in the first row of a Grid. There is some data which fills each row by double clicking on items in the GridControl below. So the main idea of it is to click on a GridControl item so it may be seen in the ListView too.
The problem is very strange: the first item is always being added and looks normally in the ListView, but then the next items can get very large, in random order.
I haven't found any ListView.Rows property or similar. So I cannot explicitly set it how I want.
There is a Grid, in which ListView is keeping:
<Grid.RowDefinitions>
<RowDefinition Height="200" x:Name="xSelectedRow"/>
<RowDefinition Height="4"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
There is ListView with some columns:
<ListView x:Name="xListSelected" BorderBrush="Transparent" Grid.Row="0"
ItemsSource="{Binding SelectedItemsSource}"
SelectedItem="{Binding SelectedSelectedItem}">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Padding" Value="10 2 4 2" />
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</ListView.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction
Command="{Binding RemoveSelectedItemCommand}"
CommandParameter="{Binding ElementName=LayoutRoot, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="{Binding Path=ActualWidth, ElementName=xProjectViewId}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding Id}"
FontSize="14"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="{Binding Path=ActualWidth, ElementName=xName}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}"
FontSize="14"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Here is a link to an image: https://imgbbb.com/image/jkdJp
There is example in the image, where the 1st, 2nd, and 3rd rows are looking normally, but the fourth is very large. And it seems not always be like this: the next two rows can be normal, but then the next three are large again.
Have you ever seen such problem?
The answer to your question about why some rows are higher is:
You set the textblocks to wrap and the strings in them then make those controls grow.
It's not random.
Decide which you prefer.
The current increased height of some rows.
Truncating the strings by setting maxheight.
Lowering the size of (presumably) the Name variable so they can only enter so much.
Some mix.
Re-arranging your UI in some other way.
Assuming that the grid you are talking about is written here:
<Grid.RowDefinitions>
<RowDefinition Height="200" x:Name="xSelectedRow"/>
<RowDefinition Height="4"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
Your height definitions for each row is inconsistent.
A specific number will give it the specific height, but some parameters might change and scale this. So this would explain why your first row remains correct.
A star (*) will tell the code to make the row proportional to the grid
"Auto" make the row to adapt to the size of the content. Wraping and padding can make this give unexpected results.
I suggest to try to either give all of the rows a large enough specific height (200) or setting all of them to Star (*)
I'm currently working on making an application CUIT-Generator ready. That means that, as an example, I'm adding XAML setters to the styles for DataGridRow that set Automation.ID and AutomationName. Works just fine.
Now my issue is that there is a ListView where the ItemTemplate contains a DataTemplate which in turn has a custom UI control.
When recording any action on the text controls inside the custom UI control, it only grabs the custom UI control and the hierarchy below it, but it doesn't record that it is inside a ListView and a ListViewItem.
Due to this, the control can not be found during test execution or when selecting the control in the UIMap and clicking Search UI control.
I tried setting the AutomationID/Name on the ListViewItem and the ListView but that does not have an impact on the recorded hierarchy.
XAML code for the ListView:
<ListView x:Name="sampleControl" Margin="3" ItemsSource="{Binding ObservableCollectionOfViewModelItems}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="AutomationProperties.Name">
<Setter.Value>
<Binding Path="AutoID"/>
</Setter.Value>
</Setter>
<Setter Property="AutomationProperties.AutomationId">
<Setter.Value>
<Binding Path="AutoID"/>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<SampleNamespace:CustomUIControlView />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code for the CustomUIControlView:
<UserControl x:Class="SampleNamespace.CustomUIControlView"
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"
mc:Ignorable="d">
<Border BorderThickness="3">
<Expander>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBox Grid.Column="1" Grid.Row="0" Name="SampleBox1" Height="20" Margin="5" Text="{Binding SampleProp1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Column="1" Grid.Row="1" Name="SampleBox2" Height="20" Margin="5" Text="{Binding SampleProp2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Column="1" Grid.Row="2" Name="SampleBox3" Height="20" Margin="5" Text="{Binding SampleProp3, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="7" Name="SampleBox4" Height="20" Margin="5" Text="{Binding SampleProp4, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Expander>
</Border>
</UserControl>
The recorded hierarchy for an action recorded on SampleBox1 looks like this:
SampleAppWindow
---- CustomUIControlView
-------- Expander
------------ SampleBox1/TextBox
Obviously none of the controls, aside from the Window are going to be found.
I know that I could transfer the recorded actions to C# code and then edit the hierarchy and search properties myself but I would like to avoid doing this as I would have to remember doing that every time a ListView is involved in a recorded test.
I'm mentioning this as most solutions here on SO or on other websites come down to working around the problem like that.
This is on Visual Studio 2017 15.3.5 and .NET Framework 4.5.2.
I'm fairly certain you are asking for something beyond what the CodedUi Code Generator can handle.
I would point out from the generated object structure it missed entirely the ListView. The route I would recommend is first being sure you can locate the ListView, generated or your own code, probably call DrawHighlight to be sure. I get your trying to avoid your own code for defining object definitions but it is probably only feasible to write your own.
Now specifically for your CustomUIControlView, I would urge you to define a matching CodedUI object that matches it. As is, an Expander with 4 children TextBoxes. This would cut down coding this definition several times. If you look at the generated code as examples to write these.
Depending on your view on designer files, you could also declare the immediately expected parent node of your ListView or itself as a partial class to hook in these unmatched children elements in a separate file to avoid it getting wiped by the generator. Then you would only need to update the designer file with the small partial statement edits.
I have started with XAML as part of my freetime and now I have a problem with the padding of the standard button.
I have the following code for a grid which resides in another grid, so I have four grids inside my page and the problem is that the buttons are cut off and I am not able to change the width or the padding of the buttons.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Center" FontSize="24"/>
<Button x:Name="Player2MinusButton" Content="-" Grid.Row="1" Grid.Column="0" FontSize="20" ></Button>
<Button x:Name="Player2PlusButton" Content="+" Grid.Row="1" Grid.Column="2" FontSize="20" ></Button>
</Grid>
The problem is now, that the button is cut of as you could see in the screenshot here:
I have already tried to set a negative padding/margin and also to make a Custom Style:
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="Padding" Value="-10,0"/>
</Style>
Thanks for your hints and I hope I have nothing forgotten in my first question.
Michael
Since you want a narrower than standard button set the Buttons' MinWidth property:
<Button x:Name="Player2PlusButton" Content="+" Grid.Row="1" Grid.Column="2" FontSize="20" MinWidth=50 AutomationProperties.Name="Plus Button" ></Button>
If you copy the button template (right click on the button in the designer then select Edit Template... and follow the prompts) you'll find the following:
<x:Double x:Key="PhoneButtonMinHeight">57.5</x:Double>
<x:Double x:Key="PhoneButtonMinWidth">109</x:Double>
I assume you're running on the phone: the Windows Store Button template is different and doesn't set the minimums. Your buttons come out small there by default.
Inside my XAML/C# app for Windows 8 Store, I am trying to create a ListView where each ListItem is a horizontal Grid, so I am using the XAML below:
<ListView Name="ResultsView">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding BestRank}" Grid.Column="0"/>
<TextBlock Text="{Binding PlayerName}" Grid.Column="1"/>
<TextBlock Text="{Binding BestScore}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When I run this program, the listview contains all the items from the list it is bound to (through code behind). However in every list-item, contents of all three columns appear together without any space between them. When I create a similar grid outside the listview, it displays fine and takes up entire width of the screen and divides it between the three columns as specified in the XAML above.
What am I doing wrong?
I believe the issue is the ItemContainerStyle needs to have a HorizontalContentAlignment of Stretch. Try this adding this to the ListView:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
Both the ListBox and the Grid should have HorizontalContentAlignment="Stretch"
Specify the width of the grid or add the style as a resource to the grid. Add this right after your </Grid.ColumnDefinitions> line.
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="Margin" Value="4" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Grid.Resources>
This will set the properties to all of the TextBlocks in the Grid. You might only need the Margin property. Also consider the properties Width and Padding. You can override this default by setting the property on any given TextBlock to something that isn't the default from the Style.
The default ItemsPanelTemplate is a stack panel as far as I recall meaning that it won't automatically give it's children stretch behavior. You will need to change it, I will edit in a sec just on my mobile waiting for my laptop to boot up :)
Edit:
Er no ignore that I was thinking of ItemsControl, JBrooks is right, just make sure HorizontalContentAlignment is set to Stretch as the default is Left.
<ListView Name="ResultsView" HorizontalContentAlignment="Stretch">
That should work fine - any controls that use XXXXContentAlignment seem to default to Left which I think its a bit inconsistent vs other controls (such as Grid)
actually this is not a problem of Listview. Problem is where you are putting it in? Put your list view in grid. It should work
<ListView Name="ResultsView"
HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding BestRank}" Grid.Column="0"/>
<TextBlock Text="{Binding PlayerName}" Grid.Column="1"/>
<TextBlock Text="{Binding BestScore}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have a databound listbox which is actually displaying two columns of data. It is displayed as follows:
<UserControl.Resources>
<DataTemplate x:Key="AlignedPairs">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Fruits}" Grid.Column="0" />
<TextBlock Text="->" TextAlignment="Center" Grid.Column="1" />
<TextBlock Text="{Binding Colors}" Grid.Column="3" />
</Grid>
</DataTemplate>
</UserControl.Resources>
<ListBox Name="lbStuff" Grid.ColumnSpan="2" Grid.Row="1"
ItemTemplate="{StaticResource AlignedPairs}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Then Itemsource set in codebehind.
Based on some logic however, I would like to set either a line or a item in one of the columns, e.g. a fruit to red, or the line to bold. I have code to work out which Fruit or Color I would like to differentiate (by color/bold) in the code behind, but I can't figure out, especially given the custom listbox display, how I could go about setting a particular item to a different color/bold.
Does anyone have any ideas?
Let me know if any further code is required. Cheers.
edit: all I really want to be able to do is make the problem as easy as possible... loop through each item in the listbox and check with a string, if there is a match SOMEHOW visually distinguish this item in the listbox/listview. There is no need to make this any more complicated than it needs to be. Why you are not able to individually set an items foreground color is beyond me!
edit 2:
It looks like I almost get there with the following (but it throws exception and doesn't work)
foreach (var li in ListView.Items)
{
if (someCriteria == true)
{
((ListViewItem) li).Foreground = Brushes.Red;
//exception throw as this is the actual object stored in this location (the Fruit object for example) not the row or listviewitem I want to change the color of so it can't be cast :(
}
}
This is where the ViewModel design pattern really helps you out.
Presumably you have a class that exposes the properties Fruit and Color. Make a wrapper class that exposes both those properties and also exposes, say, FruitBackgroundBrush and ItemBackgroundBrush. Then you can just bind to those properties in your template, e.g.:
<DataTemplate x:Key="AlignedPairs">
<Grid Background={Binding ItemBackgroundBrush}>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Fruits}"
Background="{Binding FruitBackgroundBrush}"
Grid.Column="0" />
<TextBlock Text="->" TextAlignment="Center" Grid.Column="1" />
<TextBlock Text="{Binding Colors}" Grid.Column="3" />
</Grid>
</DataTemplate>
DataTriggers will take care of this. Here's a good primer: http://en.csharp-online.net/WPF_Styles_and_Control_Templates%E2%80%94Data_Triggers