lets begin with the scenario:
I have an ItemsControl inside a UserControl. In this ItemsControl I have a dynamicly created DataTemplate which is created and added in codebehind. As there doesn't seem to be a nice way to create a DataTemplate in codebehind I had to programmatically generate the xaml code for my DataTemplate into a string and then create a DataTemplate object out of it through XamlReader:
StringBuilder stringBuilder = new StringBuilder();
XmlWriter xmlWriter = XmlWriter.Create(stringBuilder);
... // use xmlWrite to generate desired xaml
// substring is use to cut out the xml declaration
DataTemplate template = (DataTemplate)XamlReader.Load(stringBuilder.ToString().Substring(39));
myItemsControl.ItemTemplate = template;
The generated XAML code looks like this and is actually used (the items get rendered as expected):
<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid HorizontalAlignment="Stretch" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding b0}" Grid.Column="0" />
<TextBox Text="{Binding b1, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="1" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b2, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="2" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b3, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="3" LostFocus="TxtAttribute_LostFocus" IsReadOnly="True" />
</Grid>
In case you wonder: the xmlns attribute is needed by the XamlReader to render the control, else you'll get an exception when reaching the code.
My problem:
now while the items look like expected and data is correctly bound neither my customConverter that should reformat the bound data, nor the LostFocus event are correctly applied. I don't get any error messages or warnings, converter and event just don't get called. Anyone an idea why and how I can get this to work?
Update:
I reached a point where I have to solve this problem or to try a different approach.
In my last tests I tried to add the Converter directly in the DataTemplate but I had no luck. The generated code now looks like this:
<DataTemplate xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Conv="clr-namespace:my.Namespace" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid HorizontalAlignment="Stretch" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Conv:DecimalConverter x:Name="cnvDecimalConverter" />
</Grid.Resources>
<TextBlock Text="{Binding b0}" Grid.Column="0" />
<TextBox Text="{Binding b1, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="1" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b2, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="2" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b3, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="3" LostFocus="TxtAttribute_LostFocus" IsReadOnly="True" />
</Grid>
</DataTemplate>
Any ideas?
Update 2:
As I just found out XamlReader.Load() just is not able to hook up events. See this Thread in the Silverlight Forums
The Converters should work, I guess I still have some kind of namespace problem I don't see. I'm kind of out of options with my "simple" ItemsControl approach so I think it's time to look for another method to reach my needs.
Just to clear up the situation: It is not possible to generate dynamic DataTemplates with events through generating an xaml string and extract the control from this. The only option to parse xaml code with events is through Application.LoadComponent which needs a URI to work.
I ended up using nested ItemControls to create my "dynamic" behaviour.
Related
Referencing this example:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-bind-to-a-collection-and-display-information-based-on-selection
(some relevant code snippets:)
<Window.Resources>
<local:People x:Key="MyFriends"></local:People>
<DataTemplate x:Key="DetailTemplate">
<Border Width="300" Height="100" Margin="20"
BorderBrush="Aqua" BorderThickness="1" Padding="8">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="First Name:"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=FirstName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Last Name:"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=LastName}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Home Town:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=HomeTown}"/>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<ListBox Width="200" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Source={StaticResource MyFriends}}"/>
<ContentControl x:Name="contentControl1"
Content="{Binding Source={StaticResource MyFriends}}"
ContentTemplate="{StaticResource DetailTemplate}" />
Both ListBox.ItemsSource and ContentControl.Content bind to the same source (MyFriends, an instance of the People class which derives from ObservableCollection<Person>). If my understanding is correct, this means that both the ListBox.ItemsSource and ContentControl.Content properties will be bound to the same implicitly created instance of ListCollectionView.
I understand that setting ListBox.IsSynchronizedWithCurrentItem="True" synchronizes ListBox.SelectedItem and ItemCollection.CurrentItem.
DetailTemplate (above) displays the details of the selected ListBox item, despite being 'bound' to a ListCollectionView. Specifying Path=/ (what I thought would be necessary to achieve the resulting behavior) does not have any effect - it's as if WPF knows to do it implicitly somehow:
<ContentControl x:Name="contentControl1"
Content="{Binding Source={StaticResource MyFriends}, Path=/}"
ContentTemplate="{StaticResource DetailTemplate}" />
As a test, I created another ContentControl with Content bound to a DataTemplate containing a ListBox:
<ContentControl x:Name="contentControl2"
Content="{Binding Source={StaticResource MyFriends}}"
ContentTemplate="{StaticResource DetailTemplate2}" />
<DataTemplate x:Key="DetailTemplate2">
<ListBox ItemsSource="{Binding}"></>
</DataTemplate>
And it displayed the list.
My question is: Why does DataTemplate get the selected Person object while the ListBox and DetailTemplate2 get the People collection?
(the behavior is desirable, I just don't understand what black magic is occurring under the hood to make it so)
Is a good question! I didn't notice that until read your post. So, after did some digging from source code of PropertyPathWorker, it appears that when PropertyPathWorker failed to solve a member of an object, in your case, it try to solve 'FirstName', 'LastName' ect. with 'MyFriends', it will try to solve it with the view of the object. And if still failed, it will try to solve it with view's CurrentItem, and that's where the magic happened. You can find those codes in PropertyPathWorker.UpdateSourceValueState(int k, ICollectionView collectionView, object newValue, bool isASubPropertyChange) and PropertyPathWorker.ReplaceItem(int k, object newO, object parent).
I have changed the Background and Foreground Color of the MediaElement's MediaTransportControls using this solution UWP custom media controls not working
Now I want to
change the place of the 'TimeRemainingElement' and put it on the left of the Slider.
make the time show as 00:00 not 0:00:00
Is it possible to do that? Any idea how to do it?
1 more question: Is it possible to remove the "Cast to Device" icon/option from the MediaTransportControls?
Yeah, this is possible. As I've mentioned in my previous answer in UWP custom media controls not working, we can edit MediaTransportControls styles and templates to achieve what you want.
change the place of the 'TimeRemainingElement' and put it on the left of the Slider.
TimeRemainingElement is located in the Grid named "TimeTextGrid" which is in the second row of the Grid named "MediaTransportControls_Timeline_Grid". And the Slider named "ProgressSlider" is in the first row. So to put TimeRemainingElement on the left of the Slider, we can add a Grid in the first row, then remove TimeRemainingElement and ProgressSlider to the different columns of the new grid like:
<Grid x:Name="MyGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="TimeRemainingElement"
Style="{StaticResource MediaTextBlockStyle}"
Text="00:00" />
<Slider x:Name="ProgressSlider"
Grid.Column="1"
Height="33"
MinWidth="80"
Margin="12,0"
VerticalAlignment="Center"
IsThumbToolTipEnabled="False"
Style="{StaticResource MediaSliderStyle}" />
<TextBlock x:Name="TimeElapsedElement"
Grid.Column="2"
Style="{StaticResource MediaTextBlockStyle}"
Text="00:00" />
</Grid>
And set the Visibility of TimeTextGrid to Collapsed like:
<Grid x:Name="TimeTextGrid"
Grid.Row="1"
Height="15"
Margin="12,0"
Visibility="Collapsed">
<!--<TextBlock x:Name="TimeElapsedElement"
Margin="0"
HorizontalAlignment="Left"
Style="{StaticResource MediaTextBlockStyle}"
Text="00:00" />
<TextBlock x:Name="TimeRemainingElement"
HorizontalAlignment="Right"
Style="{StaticResource MediaTextBlockStyle}"
Text="00:00" />-->
</Grid>
Here we can't delete TimeTextGrid. Missing TimeTextGrid would cause exception is some scenarios.
make the time show as 00:00 not 0:00:00
Changing the format of elapsed and remaining time is not easy. They are set in code-behind, just editing properties of TimeElapsedElement or TimeRemainingElement won't work. And I'm not sure why you need them show as "00:00". What if the media's duration is large than one hour? How to show a time that is "2:10:20"? I'd suggest you just use the original format, but if you do want to show it like "00:00", here is a workaround:
Firstly, we need to create a Format Converter to convert the time format like following:
public class TimeSpanFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (!string.IsNullOrEmpty(value.ToString()))
{
var timeSpan = TimeSpan.Parse(value.ToString());
return timeSpan.ToString(#"mm\:ss");
}
else
{
return "00:00";
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Then as the Text of TimeElapsedElement and TimeRemainingElement are set in code-behind, we can't use TimeSpanFormatConverter in TimeElapsedElement and TimeRemainingElement directly. So I add two TextBlocks and bind their Text property to the Text of TimeElapsedElement and TimeRemainingElement and use TimeSpanFormatConverter in my new TextBlock like:
<TextBlock x:Name="MyTimeRemaining"
Style="{StaticResource MediaTextBlockStyle}"
Text="{Binding Text,
Converter={StaticResource TimeSpanFormatConverter},
ElementName=TimeRemainingElement}" />
The StaticResource TimeSpanFormatConverter is defined as
<local:TimeSpanFormatConverter x:Key="TimeSpanFormatConverter" />
After this, I can hide TimeTextGrid and use my TextBlocks in MyGrid:
<Grid x:Name="MediaTransportControls_Timeline_Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="MyGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="MyTimeRemaining"
Style="{StaticResource MediaTextBlockStyle}"
Text="{Binding Text,
Converter={StaticResource TimeSpanFormatConverter},
ElementName=TimeRemainingElement}" />
<Slider x:Name="ProgressSlider"
Style="{StaticResource MediaSliderStyle}"
Grid.Column="1"
Height="33"
MinWidth="80"
Margin="12,0"
VerticalAlignment="Center"
IsThumbToolTipEnabled="False" />
<TextBlock x:Name="MyTimeElapsedElement"
Style="{StaticResource MediaTextBlockStyle}"
Grid.Column="2"
Text="{Binding Text,
Converter={StaticResource TimeSpanFormatConverter},
ElementName=TimeElapsedElement}" />
</Grid>
<ProgressBar x:Name="BufferingProgressBar"
Grid.ColumnSpan="3"
Height="4"
Margin="0,2,0,0"
VerticalAlignment="Top"
IsHitTestVisible="False"
IsIndeterminate="True"
Visibility="Collapsed" />
<Grid x:Name="TimeTextGrid"
Grid.Row="1"
Height="15"
Margin="12,0"
Visibility="Collapsed">
<TextBlock x:Name="TimeElapsedElement"
Style="{StaticResource MediaTextBlockStyle}"
Margin="0"
HorizontalAlignment="Left"
Text="00:00" />
<TextBlock x:Name="TimeRemainingElement"
Style="{StaticResource MediaTextBlockStyle}"
HorizontalAlignment="Right"
Text="00:00" />
</Grid>
</Grid>
Is it possible to remove the "Cast to Device" icon/option from the MediaTransportControls?
To remove the "Cast to Device" icon/option from the MediaTransportControls, we can just delete the AppBarButton named "CastButton" in "MediaControlsCommandBar" :
<!--<AppBarButton x:Name="CastButton"
Style="{StaticResource AppBarButtonStyle}"
MediaTransportControlsHelper.DropoutOrder="7">
<AppBarButton.Icon>
<FontIcon Glyph="" />
</AppBarButton.Icon>
</AppBarButton>-->
And finally, after these changes, the MediaTransportControls will look like:
<ListView Name="myList" Background="Transparent" Margin="15,88,15,15">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="5">
<TextBlock Name="xName" Text="{Binding Name}" FontSize="30" Margin="10,0,5,0" FontWeight="Medium"/>
<TextBlock Name="xNo" Text="{Binding No}" FontSize="25" Margin="10,0,5,0" TextTrimming="CharacterEllipsis"/>
</StackPanel>
<Grid Grid.Column="1" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" Name="r1" Content="1" Width="10" Margin="5,15,-2,5"/>
<RadioButton Grid.Column="1" Name="r2" Content="2" Width="10" Margin="5,15,-2,5"/>
</Grid>
</Grid>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Now I want to retrieve each item in ListView i.e, the controls in it. The TextBlocks content and to know which RadioButton is selected.
I tried taking classes like this
public class Att
{
public string Name;
public string No;
public RadioButton r1;
public RadioButton r2;
}
There are separate sources for the content of the TextBoxes in the ListView. They come from different classes. I tried retrieving the items using above class Att.
But it is showing some type conversion errors. Please anyone help me! I'm a beginner.
Thanks is advance.
Thanks for all the support!
Well I tried doing this on my own and finally I got it. What I really wanted is to know which RadioButton is checked. I tried taking class Att for retrieving the items in ListView. I made modifications to the Att Class and added properties r1 and r2 of type bool instead of RadioButton and binded this property to the IsChecked property of the RadioButton in XAML and also mode of binding is TwoWay. So the changes done in the XAML can be reflected in the source list of items.
I am trying to get a custom UserControl to render in a ListBox, but nothing is being rendered. I came across this question and solution which works for the simple example, but my situation is a little different. I have a PersonControl for a Person object and a CoupleControl that can reference two PersonControl controls.
I've tried a couple things in the CoupleControl which haven't worked. I commented out one of the ways:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Control:PersonControl Grid.Column="0"
x:Name="LeftPerson" />
<Control:PersonControl Grid.Column="1"
x:Name="RightPerson" />
<!-- This is how I'd like to do it in case I create other controls
I wish to replace the PersonControls (e.g. AnimalControl) -->
<!--<UserControl Grid.Column="0"
x:Name="LeftPerson" />-->
<!--<UserControl Grid.Column="1"
x:Name="RightPerson" />-->
</Grid>
The relevant WPF snippet for the list box:
<ListBox Grid.Row="1"
ItemsSource="{Binding Persons}">
<ListBox.ItemTemplate>
<DataTemplate>
<Control:CoupleControl />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In the code-behind:
public ObservableCollection<CoupleControl> Persons { get; private set; }
Person joe = new Person("Joe", "Smith", Person.SexType.Male);
Person jane = new Person("Jane", "Smith", Person.SexType.Female);
PersonControl joeControl = new PersonControl();
PersonControl janeControl = new PersonControl();
joeControl.DataContext = joe;
janeControl.DataContext = jane;
CoupleControl coupleControl = new CoupleControl();
coupleControl.LeftPerson.DataContext = joe;
coupleControl.RightPerson.DataContext = jane;
//coupleControl.LeftPerson.Content = joeControl; // Also doesn't work
//coupleControl.RightPerson.Content = janeControl; // Also doesn't work
Persons.Add(coupleControl);
Can someone help me get the CoupleControl to render in a ListBox?
Your approach is a bit too code-heavy for my taste, why not set DataContext in XAML?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Control:PersonControl DataContext="{Binding LeftPerson}" />
<Control:PersonControl DataContext="{Binding RightPerson}" Grid.Column="1" />
</Grid>
Or maybe even drop UserControls altogether if they are not so complex? In this case using DataTemplates can be faster and simpler. Say we defined templates for Person and Couple in Window resources (Couple is just a class with LeftPerson and RightPerson properties):
<Window.Resources>
<DataTemplate x:Key="personTemplate" DataType="TestWPF:Person">
<Border BorderThickness="1" BorderBrush="Green" CornerRadius="5">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" Margin="3,0,0,0" />
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate x:Key="coupleTemplate" DataType="TestWPF:Couple">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding LeftPerson}"
ContentTemplate="{StaticResource personTemplate}" />
<ContentControl Content="{Binding RightPerson}"
ContentTemplate="{StaticResource personTemplate}" Grid.Column="1" />
</Grid>
</DataTemplate>
</Window.Resources>
Then you set ItemTemplate for your ListBox:
<ListBox Grid.Row="1" ItemsSource="{Binding Persons}" ItemTemplate="{StaticResource coupleTemplate}" />
This way you can make some more templates for the types you need and just set them in ListBox in one single line.
I need to fix a list with elements that have different types. Each of the type has it's own datatype to represent the viewmodel for each type. The following code works for me, but for some reason the data inside gets truncated, to some value (looks like default). I need to remove this trancation.
Here is what I have. This code is in the control, that could be placed in a list as well (it could be doubled or tripled). But I Don't think it's relevant.
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ListView DockPanel.Dock="Top" Name="testCaseResultListView"
ItemsSource="{Binding LogItems}"
ItemContainerStyleSelector="{StaticResource fixSideViewLogItemStyleSelector}"
SelectionMode="Single"
>
<ListView.View>
<GridView x:Name="gridView2">
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn CellTemplateSelector="{StaticResource fixSideViewLogItemTemplateSelector}"/>
</GridView>
</ListView.View>
</ListView>
</ScrollViewer>
</DockPanel>
fixSideViewLogItemTemplateSelector and fixSideViewLogItemStyleSelector are the selectors, that return different datatypes or styles for each of the type in LogItems. The common datatype is a grid with two columns, but that also seems irrelevent - I tried to put a textbox there, and it still gets truncated.
I would like this column to be stretched to the whole gridView. When I set width, of the column, I see the column resizing, but I want it to occupy the whole space. This should be elastic - if I put one control in the window, it should occupy the whole window, and properly resize (with it's column) when the window is resized. If I put two controls, they should divide the space by halves, and still should be resized when the window is resized.
Any help, tips?
Upd
Here is an example of the template I'm using.
<DataTemplate x:Key="testCaseDataResultTemplate">
<!-- Test case results -->
<Grid Margin="50,0,0,0" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<!--Test case result property-->
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<!--Is retry / Name-->
<RowDefinition />
<!--Test case number-->
<RowDefinition />
<!--Low limit-->
<RowDefinition />
<!--High limit-->
<RowDefinition />
<!--Measured-->
<RowDefinition />
<!--State-->
<RowDefinition />
<!--Test time-->
<RowDefinition />
<!--Comment-->
</Grid.RowDefinitions>
<!--Is retry / Name-->
<Image Grid.Column="0" Grid.Row="0"
Source="..\Resources\retry16.png"
Stretch="None" HorizontalAlignment="Left"
Visibility="{Binding Path=IsRetry, Converter={StaticResource boolToVisibilityConverter}}" />
<TextBlock Text="fh fhgfhg fhfhfhgfhg fhgfhfhgfhgfhgfhgfhgfhgf hgfhgfhgfhgfhgfhg fhfhgfhgf hgfhgfhfhg fhfhgf rdederserswerv 2" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" TextWrapping="Wrap" MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"/>
<!--Test case number-->
<TextBlock Text="Number:" Grid.Column="0" Grid.Row="1" />
<TextBlock Text="{Binding Path=TestCaseNumber}" Grid.Column="1" Grid.Row="1" />
<!--Low limit-->
<TextBlock Text="Low limit:" Grid.Column="0" Grid.Row="2" />
<TextBlock Text="{Binding Path=TestCaseData.LimitData.LowLimit}" Grid.Column="1" Grid.Row="2" />
<!--High limit-->
<TextBlock Text="High limit: " Grid.Column="0" Grid.Row="3" />
<TextBlock Text="{Binding Path=TestCaseData.LimitData.HighLimit}" Grid.Column="1" Grid.Row="3" />
<!--Measured-->
<TextBlock Text="Measured" Grid.Column="0" Grid.Row="4" />
<TextBlock Text="{Binding Path=MeasuredValue, Converter={StaticResource valasaConverter}}" Grid.Column="1" Grid.Row="4" />
<!--State-->
<TextBlock Text="Passed: " Grid.Column="0" Grid.Row="5" />
<TextBlock Text="{Binding Path=Passed}" Grid.Column="1" Grid.Row="5" />
<!--Test time-->
<TextBlock Text="Test time: " Grid.Column="0" Grid.Row="6" />
<TextBlock Text="{Binding Path=TestTime, StringFormat={}{0:hh':'mm':'ss'.'ff}}" Grid.Column="1" Grid.Row="6" />
<!--Comment-->
<TextBlock Text="{Binding Path=ShortMessage}"
Grid.Column="0" Grid.Row="7" Grid.ColumnSpan="2"
Visibility="{Binding Path=HasComment, Converter={StaticResource boolToVisibilityColConverter}}"
VerticalAlignment="Stretch"
MaxWidth="400"
TextAlignment="Center">
<TextBlock.ToolTip>
<StackPanel>
<TextBlock Text="{Binding Path=FullMessage}"/>
</StackPanel>
</TextBlock.ToolTip>
</TextBlock>
</Grid>
</DataTemplate>
It's a bit messy, but it is very simple. It has two columns - the captions, and the values. These columns are nothing to do with truncation.
I have tried also this template:
<DataTemplate x:Key="testCaseDataResultTemplate">
<TextBlock Text="Long long text goes here...... ->" HorizontalAlignment="Stretch"/>
</DataTemplate>
The text was of course longer :) It was still truncating, so I blame the listView/GridView, but not the inner template.
I think that this issue maybe is that you need to set the ListView.HorizontalContentAlignment to Stretch. Also the item container style and the item template must have the HorizontalAlignment to Stretch and the Width property must be Auto. Hope this tips helps...
EDIT
Also I think the problem could be the width of the GridViewColumn, that fix the items width
to it's own width. If you are using a single column, maybe you can change the ListView to a ListBox or an ItemsControl, just an idea.
I don't know what your templates looks like but I see a problem like this, it normally lies with a TextBlock that isn't wrapping and/or that the TextBlock's width is longer than it's parent.
Cannot say that I solved the puzzle, but at least it works as I expected. I removed the whole definition with GridView and columns inside, and put ItemTemplateSelector directly in ListView.
So my ListView looks now like this:
<ListView DockPanel.Dock="Top" Name="testCaseResultListView"
ItemsSource="{Binding LogItems}"
ItemContainerStyleSelector="{StaticResource fixSideViewLogItemStyleSelector}"
SelectionMode="Single"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
ItemTemplateSelector="{StaticResource fixSideViewLogItemTemplateSelector}">
That did it! Hope that will help to somebody as well.