XAML displaying system message when using datatemplate - wpf

When trying to create a simple datatemplate to change the visibility of a text block from collapsed to visible my window is displaying the text;
System.windows.DataTemplate
And nothing else.
My code;
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Visibility="Collapsed" Name="one" Grid.Row="0" Grid.Column="0">One</TextBlock>
<TextBlock Visibility="Collapsed" Name="two" Grid.Row="0" Grid.Column="0">Two</TextBlock>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.isCorrect}" Value="true">
<Setter TargetName="one" Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Data.isCorrect}" Value="false">
<Setter TargetName="two" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
isCorrect is simple declared within the Xaml.cs file as;
public Boolean isCorrect = true;
An additional question if I'm allowed to whilst I'm here. As far as I understand the use of;
Data.isCorrect
Gets the value from the cs file, but is there any documentation about this as I've been unable to find anything to do with the Data keyboard as I've simply picked it up through tutorials.

Related

WPF VB.NET ListView DataTemplate change

I'm trying to replicate the functionality you have in Windows Explorer for changing layout via a series of layout toggle buttons. Layouts such as "List", "Details", "Tiles", etc etc.
I've found several other posts on this, but none have really answered the problem for me, plus they are all C# and I've not used C# so trying to decipher the answers is extremely frustrating.
This is what I've got so far - I'm starting with just List and Details while trying to get is working, but plan to add in Tiles and Content as well:
XAML:
<Window.Resources>
<DataTemplate x:Key="List_Template">
<Grid...>
</DataTemplate>
<DataTemplate x:Key="Details_Template">
<Grid...>
</DataTemplate>
<DataTemplate x:Key="SelectedItem_Template">
<Grid...>
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="List_ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource List_Template}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedItem_Template}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ListBoxItem}" x:Key="Details_ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource Details_Template}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedItem_Template}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
I'm using Radio buttons to change the layout for simplicity at the moment, but will at some point change them to buttons that resemble the Windows Explorer options:
<Grid Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<RadioButton x:Name="List_RadioButton" Content="List" Grid.Row="0" Grid.Column="0" Margin="8,0,8,0" VerticalAlignment="Center"
Foreground="{DynamicResource LightFont_Colour}"
IsChecked="True"/>
<RadioButton x:Name="Details_RadioButton" Content="Details" Grid.Row="0" Grid.Column="1" Margin="8,0,8,0" VerticalAlignment="Center"
Foreground="{DynamicResource LightFont_Colour}"
IsChecked="False"/>
</Grid>
The ListView is Data Bound to a view from SQL Server. by default i want it to be on List layout if not manually set by the user:
<Grid x:Name="Grid_Body" Grid.Row="3" Grid.ColumnSpan="2" >
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ListView x:Name="DataList_ListView"
Grid.Row="0" SelectionMode="Single" SelectedValuePath="ID"
IsSynchronizedWithCurrentItem="True"
DataContext="{Binding}"
ItemContainerStyle="{StaticResource List_ContainerStyle}"
Background="{DynamicResource WhiteBackground_90Transparent}" Margin="0,0,0,0">
</ListView>
</Grid>
VB.NET - I've been trying to find a way to change the ItemContainerStyle in code when i hit the RadioButton to change to details layout or back to list layout. The below does not work and was partially lifted from another stackoverflow post:
Private Sub List_RadioButton_Checked(sender As Object, e As RoutedEventArgs) Handles List_RadioButton.Checked
CaseList_ListView.ItemContainerStyle = DirectCast(Resources("List_ContainerStyle"), System.Windows.Style)
End Sub
Private Sub Details_RadioButton_Checked(sender As Object, e As RoutedEventArgs) Handles Details_RadioButton.Checked
CaseList_ListView.ItemContainerStyle = DirectCast(Resources("Details_ContainerStyle"), System.Windows.Style)
End Sub
Any help would be appreciated.

Add colon at the end of the text or right aligned depending on the value of RowSpan of a textblock

I have a textblock as mentioned in code below:
<TextBlock Grid.Row=........
.................
Grid.RowSpan="{Binding RowSp}"
HorizontalAlignment="Left" />
Now I want to check if RowSpan > 1 then I want to add a space and a Colon at the end of the text.I think(not tried) I have got it using Triggers and Converter as mentioned in Code below:
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="{Binding RowSp,
Converter={StaticResource colonAlignmentConverter}}"
Value="True" >
<Setter Property="Text"
Value="{Binding Txt,
Converter=ColonAlignmentConverter}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
public class ColonAlignmentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (int)value > 1;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Now the problem is here:
If RowSpan = 1 then I want to add colon(:) in the same Grid.Row and Grid.Column but I want it right aligned. How can I achieve this?
I can use another textblock for colon if it is possible.
This would usually be done with templates but, as you already know, you cannot template a TextBlock.
However, when you pass a string to the Content property of a ContentControl, the ContentControl uses a TextBlock to display the string. This was discovered by using Snoop, an awesome WPF debugging tool.
Taking this into account, the fact that Grid.RowSpan for any child of a Grid has a default value of 1, and that you want to display a colon whenever the TextBlock has a RowSpan greater than 1, the following will do what you want.
<Window x:Class="StackOverflow._20820850.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="TextBlockContentControlStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<TextBlock Text="{TemplateBinding Content}" />
<TextBlock Text=":" HorizontalAlignment="Right"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Grid.RowSpan" Value="1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<TextBlock Text="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentControl Content="One" Style="{StaticResource TextBlockContentControlStyle}" />
<ContentControl Content="Two" Grid.Column="1" Grid.RowSpan="2" Style="{StaticResource TextBlockContentControlStyle}" />
</Grid>
</Window>
Things to note
I have replaced the TextBlock with a ContentControl (I am not sure if this option is available to you)
I wanted to use a pure XAML approach so my default template is the template that manages RowSpan > 1. I then supply a trigger to set the template back to the default RowSpan = 1.
This needs to be a keyed style as setting this as a default style will probably break every other control that utilises the ContentControl in its Logical or Visual tree.
If you do not want to use a ContentControl, another approach would be to create your own UserControl. In the following, I have created a control called MyTextBlock (I could have called it TextBlock and let the namespacing sort it out but this is clearer in an example) and I then Templated the content of the Control. The XAML of the user control is
<UserControl x:Name="ThisControl" x:Class="StackOverflow._20820850.MyTextBlock" 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" d:DesignHeight="300" d:DesignWidth="300">
<UserControl.ContentTemplate>
<DataTemplate>
<Grid DataContext="{Binding ElementName=ThisControl}">
<TextBlock Text="{Binding Path=Content}" />
<TextBlock Text=":" HorizontalAlignment="Right">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding (Grid.RowSpan)}" Value="1">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</DataTemplate>
</UserControl.ContentTemplate>
</UserControl>
And the grid in the Window now looks like
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<this:MyTextBlock Content="One" />
<this:MyTextBlock Content="Two" Grid.Column="1" Grid.RowSpan="2" />
</Grid>
Obviously, the colon can be missed as it is pushed right up against the right hand side of the control but I will leave formatting to you.
I hope this helps.

Apply style to Silverlight control only when that control is inside another control with specific style

I have a Grid control where each row contains a stackpanel, and each stackpanel contains one or more textblocks (while not the core of the question, if there's a better way to achieve a custom grid of textblocks - i.e. rows of "header label: content", I'd appreciate some tips)
Anyway... I want to have a header row, where the stackpanel has a dark background and the textblock has white, bold text, and then each other row to have black text. Note that only the first row is defined with Style HeaderRow. I've used the "BasedOn" to define that only textblocks within a header row should be bold/white, however I'm finding that this impacts all textblocks in other rows too (that don't have another style defined).
I'd effectively like to be able to do
Sample XAML
Styles:
<Style x:Key="TitleLabel" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="Margin" Value="5 0 0 0"/>
<Setter Property="Width" Value="105"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
<Style x:Key="AlternatingRow" TargetType="StackPanel">
<Setter Property="Background" Value="#f0f1ff"/>
</Style>
<Style x:Key="HeaderRow" TargetType="StackPanel">
<Setter Property="Background" Value="#666666"/>
</Style>
<Style TargetType="TextBlock" BasedOn="StaticResource HeaderRow" >
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Style="{StaticResource HeaderRow}">
<TextBlock Text="Header Row" />
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="1" Style="{StaticResource AlternatingRow}">
<TextBlock Text="HeaderLabel:" Style="{StaticResource TitleLabel}" />
<TextBlock Text="Content" />
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="2">
<TextBlock Text="HeaderLabel" Style="{StaticResource TitleLabel}" />
<TextBlock Text="Content" />
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="3" Style="{StaticResource AlternatingRow}">
<TextBlock Text="HeaderLabel" Style="{StaticResource TitleLabel}" />
<TextBlock Text="Content" />
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="4">
<TextBlock Text="HeaderLabel" Style="{StaticResource TitleLabel}" />
<TextBlock Text="Content" />
</StackPanel>
</Grid>
You are not using Style BasedOn property correctly. All it does is indicate that one style 'extends' another, i.e. it copies all its setter values. (Note, your example will also fail because you are trying to base on style on another where the TargetTypes are not compatible) It does not indicate that a style is applied when one element is nested inside another.
Unfortunately Silverlight does not have the feature you require, you cannot style based on element location within the visual tree. You are going to have to style each TextBlock explicitly.
Although, I did create a mechanism for using CSS for styling a while back:
http://www.scottlogic.co.uk/blog/colin/2009/03/using-css-selectors-for-styling-in-wpf/
This allows you to create selectors based on parent elements.

Show "pop up window" when is mouser over listBox item

I bind observable collection on listBox. I have data tempate on listbox item. It consit one image control and som textBlock.
If is mouse over on some listBox item I would like achieve this behavior:
Show PopUp/ToolTip (some "rectangle" with controls) and bind values from listBox current item.
And on textBox in item data template I have style, I would like change color of text in textBlock, for example from black to green.
Style is here:
<Style x:Key="FriedNickStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="2,2,2,2"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
Sory for my english, I have problem how describe this behavior correct. I try many thing but any of them doesn’t work good.
Here is it my style:
<DataTemplate x:Key="FriendListBoxItemTemplate">
<Grid Name="RootLayout">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
</Grid.RowDefinitions>
<Image Margin="4,4,4,2" Grid.Column="0">
<Image.Source >
<MultiBinding Converter="{StaticResource avatarConverter}">
<Binding Path="ProfilePhoto"></Binding>
<Binding Path="StatusInfo.IsLogged"></Binding>
</MultiBinding>
</Image.Source>
</Image>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock
Text="{Binding Path=Nick}"
Style="{StaticResource FriedNickStyle}"
Grid.Column="0" Grid.Row="0">
</TextBlock>
</Grid>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--SHOW SOME POP UP WINDOW and bind properties from ITEM (VALUE)-->
<!--Change color of textBlock-->
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
Thank everybody who help me.
Well, I found this turorial, this article, by the MSDN and another stack overflow's question.
Basically, here's how:
<Popup Margin="10,10,0,13"
Name="Popup1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="194"
Height="200"
IsOpen="True"> // change this to open it
<TextBlock Name="McTextBlock" Background="LightBlue" >
This is popup text
</TextBlock>

How do I Show/Hide a Grid Row and Grid Splitter based on a Toggle Button?

Currently I have a toggle button that is bound to a boolean property (DualLayout) in my code behind. When the boolean is set to True, then I want my second row in my grid (and grid splitter) to hide and have the first row take up the entire space of the grid. Once the boolean is set to False, I want the grid splitter and bottom row to appear.
Here is a snippet of my xaml
<ToggleButton Name="toggleLayout" Margin="66,1,0,1" Width="25" HorizontalAlignment="Left" IsChecked="{Binding DualLayout}" Checked="toggleLayout_Clicked" Unchecked="toggleLayout_Clicked">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type ToggleButton}">
<Image Source="Images/PlayHS.png"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Receive and Transmit Windows Split."/>
</Trigger>
<Trigger Property="IsChecked" Value="false">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="{x:Type ToggleButton}">
<Image Source="Images/PauseHS.png"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Receive and Transmit Windows Combined."/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Grid x:Name="transmissionsGrid" Margin="0,28,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" MinHeight="100" />
</Grid.RowDefinitions>
<transmission:TransmissionsControl x:Name="transmissionsReceive" TransmissionType="Receive" Margin="0,0,0,5" />
<GridSplitter Name="gridSplitter1" Grid.Row="0" Background="White" Cursor="SizeNS" Height="4" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Foreground="Firebrick" />
<transmission:TransmissionsControl x:Name="transmissionsTransmit" TransmissionType="Transmit" Grid.Row="1" />
</Grid>
This is untested, but I believe it should work.
First, if you want your first row to take up the whole space, you'll want to define your RowDefinitions as
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" /> <!-- Edit: Removed MinHeight="100" -->
</Grid.RowDefinitions>
For showing/hiding the controls, you'll need to bind their Visibility property either to your DualLayout property (if the class properly implements INotifyPropertyChanged), or (perhaps more simply) to the IsChecked property of the ToggleButton.
For instance (the same applies to the GridSplitter):
<!-- EDIT: Added MinHeight="100" here instead -->
<transmission:TransmissionsControl x:Name="transmissionsTransmit"
TransmissionType="Transmit"
Grid.Row="1"
MinHeight="100"
Visibility={Binding ElementName=toggleLayout,
Path=IsChecked,
Converter={StaticResource boolToVis}}" />
At some level above the controls in question (here I am doing it at the window level) you need to add built-in BooleanToVisibilityConverter resource:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="boolToVis" />
</Window.Resources>

Resources