I want to change Button formating whenever the item in ItemsControl bool property is true. However, this formatting is not working.
.cs:
<ItemsControl ItemsSource="{Binding MyList}">
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Selected}" Value="True">
<Setter Property="Button.BorderBrush" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding Selected}" Value="False">
<Setter Property="Button.BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource ButtonStyle}">
<StackPanel Orientation="Horizontal">
<Image Style="{StaticResource ImageStyle}" Source="{Binding Icon}"/>
<TextBlock Style="{StaticResource BrightText}" Text="{Binding Title}"
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I've tried to add TargetType of Button to Style with Setter property only BorderBrush but that didn't help either.
I have a textbox:
<TextBox Grid.Row="3"
Grid.Column="1"
Width="200"
TextWrapping="Wrap"
VerticalAlignment="Top"
Margin="5,10,-10,2"
Style="{StaticResource TextBoxValueStyle}"
Validation.ErrorTemplate="{StaticResource ValidationControlTemplate}">
<TextBox.Text>
<MultiBinding StringFormat=" {0} {1}">
<Binding Path="Id" ValidatesOnNotifyDataErrors="True" NotifyOnValidationError="True"/>
<Binding Path="Name" />
</MultiBinding>
</TextBox.Text>
</TextBox>
And here is my controltemplate:
<ControlTemplate x:Key="ValidationControlTemplate">
<DockPanel Visibility="{Binding ElementName=Placeholder, Path=Visibility}">
<Image x:Name="Image"
DockPanel.Dock="Right"
VerticalAlignment="Center"
Margin="0,-2"
Style="{StaticResource InformationImageStyle}">
<Image.ToolTip>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Image.ToolTip>
</Image>
<AdornedElementPlaceholder Name="Placeholder" VerticalAlignment="Center"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="TextBox.Text" Value="">
<Setter Property="DockPanel.Dock" TargetName="Image" Value="Left"/>
<Setter Property="Margin" TargetName="Image" Value="-20,-2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
My issue is that when the textbox has a value (and has error)it is NOT taking the original values (DockPanel.Dock=Right and Margin=0,-2)
I am always starting with text empty. The image is always showing to the left, on error.
What am I missing?
Put a Grid around the <AdornedElementPlaceholder /> element and replace the Trigger with a DataTrigger that binds to the adorned TextBox element:
<ControlTemplate x:Key="ValidationControlTemplate">
<DockPanel Visibility="{Binding ElementName=Placeholder, Path=Visibility}">
<Image x:Name="Image"
DockPanel.Dock="Right"
VerticalAlignment="Center"
Margin="0,-2"
Style="{StaticResource InformationImageStyle}">
<Image.ToolTip>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Image.ToolTip>
</Image>
<Grid>
<AdornedElementPlaceholder Name="Placeholder" VerticalAlignment="Center"/>
</Grid>
</DockPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding AdornedElement.Text.Length, ElementName=Placeholder}" Value="0">
<Setter Property="DockPanel.Dock" TargetName="Image" Value="Left"/>
<Setter Property="Margin" TargetName="Image" Value="-20,-2"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I have the following definition of a UserControl
<UserControl x:Class="Logger.View.AdvancedToggleButton"
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"
xmlns:converter="clr-namespace:Logger.Converter"
xmlns:commonControls="clr-namespace:Logger.CommonControls"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<UserControl.Resources>
<converter:CountToVisibilityConverter x:Key="CountToVisibilityConverter" />
</UserControl.Resources>
<ItemsControl ItemsSource="{Binding LogElements, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<Style TargetType="{x:Type ToggleButton}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="container"
BorderThickness="1" Margin="1,2,1,1" Padding="2,2,4,2" BorderBrush="Black">
<ContentPresenter x:Name="contentPresenter" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="container" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<Setter Property="BorderThickness" TargetName="container" Value="1,1,1,0"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" TargetName="container" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<Setter Property="Background" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ToggleButton Margin="2,1"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Command="{Binding DataContext.ToggleCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
CommandParameter="{Binding}">
<ToggleButton.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0" x:Name="tbText"/>
<Border Grid.Column="1" Margin="0,-1,-3,-1" MinWidth="20"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Background="Yellow" BorderBrush="LightGray" BorderThickness="1,0,0,0"
Visibility="{Binding WarningCount, Converter={StaticResource CountToVisibilityConverter}}"
Cursor="Hand">
<commonControls:ActionLink HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding WarningCount}"
FontFamily="Consolas" Margin="2,0" Command="{Binding DataContext.NavigateToWarningCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</Border>
<Border Grid.Column="2" Margin="3,-1,-3,-1" MinWidth="20"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Background="Red" BorderBrush="LightGray" BorderThickness="1,0,0,0"
Visibility="{Binding ErrorCount, Converter={StaticResource CountToVisibilityConverter}}"
Cursor="Hand" >
<commonControls:ActionLink HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ErrorCount}"
FontFamily="Consolas" Foreground="White" Margin="2,0" />
</Border>
</Grid>
</ToggleButton.Content>
</ToggleButton>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
Everything just works fine. Now I've added another Property to this UserControl to set the BackgroundColor of the Checked ToggleButton-TextBlock (tbText) to a given SolidColorBrush.
My problem now is, that I have no idea how to correctly set the Trigger for this.
I tried to add the Trigger to the ControlTemplate.Triggers when the IsChecked is True. But I don't know how to access tbText from this point. Is this the correct location for the Trigger or do I have to add another Trigger at a lower level?
Your ToggleButton.IsChecked property is data bound to your IsSelected property so by default, you also want to set the TextBlock.Background when this IsSelected property is true. You can do that like this:
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0"
x:Name="tbText">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="{Binding YourColourBrush,
RelativeSource={RelativeSource AncestorType={x:Type
YourPrefix:YourUserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
Alternatively, you could just data bind directly to the ToggleButton.IsChecked property like this:
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0"
x:Name="tbText">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource
AncestorType={x:Type ToggleButton}}}" Value="True">
<Setter Property="Background" Value="{Binding YourColourBrush,
RelativeSource={RelativeSource AncestorType={x:Type
YourPrefix:YourUserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
I am working on a C# WPF project and I have a list view which uses data binding and a collection view.
Below is how my ListView is currently populated.
<ListView HorizontalAlignment="Left" Margin="547,12,0,41" Name="lstCallLogInformation" Width="320">
<ListView.Style>
<Style TargetType="ListView">
<Style.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<TextBlock Text="No items in your devices call log" FontWeight="Bold" HorizontalAlignment="Center" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Style>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="Gray" Text="{Binding Name}" VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Control.HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel Style="{StaticResource onmouseover}">
<StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal" Tag="{Binding logID}">
<Image Height="30" Source="{Binding base64ImageString, Converter={StaticResource ImageConverter}}" Width="30" />
<StackPanel Margin="10" Orientation="Vertical">
<TextBlock FontWeight="Bold" Text="{Binding contactNameOrPhoneNumber}" />
<StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" Text="{Binding dateString}" />
<TextBlock Margin="15, 0, 0, 0" Text="Duration: " />
<TextBlock HorizontalAlignment="Right" Text="{Binding humanReadableCallDuration}" />
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button Background="Transparent" BorderThickness="0" BorderBrush="Transparent" Tag="{Binding logID}" Name="btnAddAsContact" Click="btnAddAsContact_Click">
<Image Width="15" Height="15" Source="/BoardiesSMSServer;component/images/add.png" Tag="{Binding logID}" />
</Button>
<Button Background="Transparent" BorderThickness="0" BorderBrush="Transparent" Tag="{Binding logID}" Name="btnDeleteContactFromLog" Click="btnDeleteContactFromLog_Click">
<Image Width="15" Height="15" Source="/BoardiesSMSServer;component/images/delete.png" Margin="0,0,0,5" Tag="{Binding logID}" />
</Button>
</StackPanel>
</StackPanel>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Within my DockPanel within the DataTemplate I have a StackPanel which contains various TextBlocks from the array that is passed into the binding.
In one of the StackPanels you will see you will see a TextBlock that binds to the element of contactNameOrPhoneNumber.
What I want to be able to do is if another value from the binding is null then I add a TextBlock for the contactNameOrPhoneNumber` element and alongside it have another TextBlock which contains another element of number``, if the other binding value is not null then this extra textblock of number is not added.
So in simple terms, what I want to be able to do is within the DataTemplate have a conditional if statement of if binding value == null add textblock to stackpanel else don't add textblock.
You can do that with Style + Triggers something like this:
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding PropertyName}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Also you can create IValueConverter say ObjectToVisibilityConverter which will take input your property and if property is null return Visibility.Collapsed else return Visibility.Visible.
You can then bind property with Visibility value of TextBlock via Converter.
<TextBlock Visibility="{Binding PropertyName,
Converter={StaticResource ObjectToVisibilityConverter}}"/>
I have the following Listbox:
<ListBox Margin="5" Grid.Column="0" Name="ListboxSelectUpdate">
<ListBox.ItemTemplate>
<DataTemplate>
<ProgressBar Visibility="Visible">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding Progress}" Value="0">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
<ProgressBar.Template>
<ControlTemplate>
<AdornedElementPlaceholder Name="adorner">
<Grid>
<TextBlock Width="70" FontStyle="Italic" FontWeight="Bold">Version:</TextBlock>
<TextBlock FontWeight="Bold" Text="{Binding Path=Version}"></TextBlock>
</Grid>
</AdornedElementPlaceholder>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this Listbox I want to show different available Updates / Versions for a program.
Now I want to have a Progressbar in the Background of the ItemTemplate, which is only visible if the Progess-Property (int) is not zero. (so if the Update starts, the Progress-Property isnt zero and the Progressbar should be visible).
My Problem: I cant see anything, no Progressbar and no TexbBlocks.
Where is my misstake?
Your template is a bit wrong. You have misused AdornedElementPlaceholder element which, according to MSDN should be used only for validation templates. And you don't put things inside AdornedElementPlaceholder, it's a place where decorated control is put. If you want to stack controls on top of each other then use Grid. Try this ListBox template instead:
<ListBox Margin="5" ItemsSource="{Binding Path=MyList}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding Progress, Mode=OneWay}">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Style.Triggers>
<DataTrigger Binding="{Binding Progress}" Value="0">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
<StackPanel Orientation="Horizontal">
<TextBlock Width="70" FontStyle="Italic" FontWeight="Bold">Version:</TextBlock>
<TextBlock FontWeight="Bold" Text="{Binding Path=Version}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>