TextBox validation sets Button border to red - c#

I have an ItemsControl where I dynamically create a new GroupBox with several controls in it and model behind. That works so far. I've also implemented validation to my TextBoxes, which is also working as intended. And there is a Button to remove this GroupBox, which binds to the Ancestor of type UserControl.
<ItemsControl Grid.Row="2" ItemsSource="{Binding StorageLocationList, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox Style="{StaticResource GroupBoxBase}">
<GroupBox.Header>
<CheckBox x:Name="ExportGroupCheckBox" Content="Storage Location active" IsChecked="{Binding GroupActive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource CheckBoxBase}" IsEnabled="{Binding ElementName=ActivateExportCheckBox, Path=IsChecked}"/>
</GroupBox.Header>
<Grid>
<Grid IsEnabled="{Binding ElementName=ExportGroupCheckBox, Path=IsChecked}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Name:" VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource LimitedCharTextBox}" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Label Grid.Row="1" Grid.Column="0" Content="Storage Location:" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Style="{StaticResource BaseTextBox}" Text="{Binding StorageLocationPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Browse..." VerticalAlignment="Stretch" Command="{Binding StorageLocationBrowseCommand}" Style="{StaticResource ButtonBase}"/>
</Grid>
<Canvas>
<Button Canvas.Top="0" Canvas.Right="0" Content="X" ToolTip="Remove Group" Style="{StaticResource RemoveButton}" Command="{Binding ElementName=GPUserControl, Path=DataContext.RemoveStorageLocationGroupCommand}" CommandParameter="{Binding}"/>
</Canvas>
</Grid>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When I now type something wrong in the TextBox that is bound to the Name property, the validation takes place and the TextBox receives a red border to indicate that. Cool. But the button to remove this GroupBox also gets a red border. And that's weird.
I also tried to set the Validation.ErrorTemplate of the Button to null like so:
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
but that sets the TextBox Validation.ErrorTemplate to null as well.
So how are they connected to each other? Somehow through the UserControl?
Here is a screenshot of it:
EDIT:
Here are the Styles:
<Style x:Key="BaseTextBox" TargetType="TextBox">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="GroupBoxBase" TargetType="GroupBox">
<Setter Property="Padding" Value="2"/>
</Style>
<Style x:Key="ConfigurationMainWindownButton" TargetType="Button">
<Setter Property="Height" Value="Auto"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Margin" Value="2,2,2,2"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style x:Key="RemoveButton" TargetType="Button" BasedOn="{StaticResource ConfigurationMainWindownButton}">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="Bold"/>
<!-- <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> -->
</Style>

WPF marks all your ItemsControl as not valid not only your text box inside due to using the same data model (actually model is not valid - not controls) . Text box just set state to invalid value. You could resolve it with overriding Validation.ErrorTemplate style setting for Remove Group button control if the button have to ignore validate state of model .
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<AdornedElementPlaceholder />
</ControlTemplate>
</Setter.Value>
</Setter>

Related

WPF Custom Template button with rounded corners not responding sometimes

Im currently working on a UI with WPF embedded in a ElementHost Control(Winform) for a powerpoint add-in. The appearance for the button works fine, however sometimes when entering the button it simply doesn't respond, meaning that hover/press events are not fired and when I click on it selects the parent behind it (probaly since nothing is selected) as if the button was a ghost. When i remove the border inside the template that displays the rounded rectangle the problem dissapears, a default button also doesnt suffer from the same problem. However if the custom button has focus on it, it works flawlessly. So far my best guess is performance related issues.
Grid inside usercontrol that holds the buttons:
<Viewbox Grid.Column="2" Grid.RowSpan="3" HorizontalAlignment="Right" Margin="0,5,10,5">
<Grid Height="100" Width="100">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Background="red" Style="{StaticResource AnchorPoint}" Click="Button_Click_1"/>
<!--<Button Grid.Row="0" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="0" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="0" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="2" Grid.Column="0" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="2" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>-->
<Button Grid.Row="2" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Content="Button" Grid.Column="2" Grid.Row="1"/>
</Grid>
</Viewbox>
Style for button:
<Style TargetType="Button" x:Key="AnchorPoint">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="Foreground" Value="Transparent"></Setter>
<Setter Property="BorderBrush" Value="{x:Null}"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
<Setter Property="Margin" Value="0,0,0,0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" CornerRadius="2" Margin="0" BorderThickness="2" Style="{StaticResource TestHidden}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red" TargetName="border"></Setter>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="blue" TargetName="border"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="green" TargetName="border"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Style for Border:
<Style x:Key="TestHidden" TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}"/>
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Focusable" Value="False"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}" />
<Setter Property="Background" Value="{StaticResource SkyGreyHover}" />
</Trigger>
</Style.Triggers>
</Style>
My hunch is that the problem is related to setting the Background Property of the Border (Key="TestHidden") default to {x:Null}. Although it seems odd, setting the Background to null for a UIElement can cause the element to be invisible to mouse events. This is probably why the element behind the border is the one capturing mouse events instead - making the border seem like a "Ghost". Set the borders default background to Transparent.
<Style x:Key="TestHidden" TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}"/>
<Setter Property="Background" Value="Transparent" />
You might ask why parent button (Key="AnchorPoint") is not capturing mouse events instead: Although the Buttons Background is correctly set to Transparent, this property is being ignored by WPF because it is not referenced in the ControlTemplate via TemplateBinding. If you want the buttons background property to actually show up in the control, use a TemplateBinding on the control responsible for displaying the Background color (the border):
<Border x:Name="border"
CornerRadius="2"
Margin="0"
BorderThickness="2"
Style="{StaticResource TestHidden}"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content"/>
</Border>
Note: There are various other occurrences in your XAML where the issues described above might exist. Hope this helps.

Unable to remove error state from WPF DataGrid Cell

I have a WPF datagrid using the WpfToolkit version 3.5.40128.1
For one cell I raise a PropertyChanged event that the viewmodel has a listener for, and determines if the value is duplicated to the other values. If it is duplicated, a state is set on the object and the cell is put into an error state.
So a user can enter Priority in the first record to 2 and the second field to 2 and the second value is in error.
When the user changes the error field all works as expected.
When the user changes the first '2' to 1 the second field is no longer duplicated and the flag is cleared. However, no matter what I do, the field remains in error. I have tried the following:
1) I added a PropertyChanged event call on the field even though it is in an ObservableCollection. This caused a regular check for duplicate values but did not remove the red outline.
2) I added event styles for both ValidationErrors==true as well as ValidationErrors==false. This sounded hopeful but it only clears the tooltip it does not clear the red outline.
3) I added a PropertyChanged call on the state boolean when it's value changes.
Playing with the field myself manually in the form, if I enter and exit the field it remains in error. If I enter the field and re-enter '2' the error state goes away.
I'm at a loss now as to what else to do! Any suggestions on additional things to try would be helpful.
Below is the style and definitions of the datagrid. Priority is the only field being validated.
<!-- style to apply to DataGrid TextBlock -->
<Style x:Key="DataGridTextBlockStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid CheckBox -->
<Style x:Key="DataGridCheckBoxStyle" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid TextBox in edit mode -->
<Style x:Key="CellEditStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid Checkbox in edit mode -->
<Style x:Key="CheckboxEditStyle" TargetType="{x:Type CheckBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
</Style.Triggers>
</Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="345*"/>
<ColumnDefinition Width="88*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" VerticalAlignment="Top"
Margin="2,2,2,0" Header="Region Selection"
BorderBrush="White" BorderThickness="0" Grid.ColumnSpan="2">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical" Height="120"
VerticalAlignment="Top" Background="White">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="5,5,5,5" Height="101" >
<wpftk:DataGrid x:Name="SegmentGrid"
IsEnabled="True"
AutoGenerateColumns="False"
VerticalScrollBarVisibility="Auto"
Height="90"
ItemsSource="{Binding SegmentList}" CanUserAddRows="False" CanUserDeleteRows="False" >
<wpftk:DataGrid.Columns>
<!-- The Region Name Column -->
<wpftk:DataGridTextColumn Header="Name"
Width="265"
Binding="{Binding RegionName}" />
<!-- The Priority Column -->
<wpftk:DataGridTemplateColumn Header="Priority" Width="60">
<wpftk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource DataGridTextBlockStyle}"
Text="{Binding Priority, Mode=TwoWay,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellTemplate>
<wpftk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox>
<TextBox.Text>
<Binding Path="Priority"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True" >
</Binding>
</TextBox.Text>
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource CellEditStyle}" />
</TextBox.Style>
</TextBox>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellEditingTemplate>
</wpftk:DataGridTemplateColumn>
<!-- The Write To Cartridge Column -->
<wpftk:DataGridTemplateColumn Header="Write To Cartridge" Width="80">
<wpftk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource DataGridCheckBoxStyle}"
IsChecked="{Binding WriteToCartridge, Mode=TwoWay,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellTemplate>
<wpftk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<CheckBox>
<CheckBox.IsChecked>
<Binding Path="WriteToCartridge"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True"
ValidatesOnExceptions="True" >
</Binding>
</CheckBox.IsChecked>
<CheckBox.Style>
<Style TargetType="CheckBox" BasedOn="{StaticResource CheckboxEditStyle}" />
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellEditingTemplate>
</wpftk:DataGridTemplateColumn>
</wpftk:DataGrid.Columns>
</wpftk:DataGrid>
</ScrollViewer>
</StackPanel>
</Grid>
</GroupBox>
Needed to expose a new method inside the object for INotifyPropertyChanged.
This allowed us to examine all of the objects in the array, and when we changed the value we called it from the object rather than from the viewmodel. This caused the automatic finding and clearing of any object that was duplicated within the array.

WPF Textbox and Label are overlapping

I am learning WPF (Windows Presentation Foundation) on Visual Studio 2013. I have an issue with the layout of elements. I am using stackpanel and grid for element layout. Here is the simple layout which i have created:
... code omitted....
<StackPanel Style="{StaticResource ersStackPanel}">
<Grid Style="{StaticResource ersGrid}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="497*"/>
</Grid.ColumnDefinitions>
<Label Content="Elector's record scrapper" Style="{StaticResource ersHeadLabel}" />
</Grid>
<Grid Style="{StaticResource ersGrid}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150*"/>
<ColumnDefinition Width="347*"/>
</Grid.ColumnDefinitions>
<Label Content="VS" Style="{StaticResource ersLabel}"/>
<TextBox x:Name="VS" Grid.Column="1" Style="{StaticResource ersTextBox}" />
<Label Content="EV" Grid.Row="1" Style="{StaticResource ersLabel}"/>
<TextBox x:Name="EV" Grid.Row="1" Grid.Column="1" Style="{StaticResource ersTextBox}" />
<Label Content="ENo." Grid.Row="2" Style="{StaticResource ersLabel}"/>
<TextBox x:Name="ENo" Grid.Row="2" Grid.Column="1" Style="{StaticResource ersTextBox}" />
<Label Content="Select" Grid.Row="3" Style="{StaticResource ersLabel}"/>
<ComboBox Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" FontFamily="Verdana" FontSize="10" Background="White"/>
</Grid>
</StackPanel>
... code omitted...
Style Resource
<Window.Resources>
<Style x:Key="ersTextBox" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="10"></Setter>
<Setter Property="FontFamily" Value="Verdana"></Setter>
<Setter Property="FontWeight" Value="Medium"></Setter>
<Setter Property="Width" Value="250"></Setter>
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
<Setter Property="VerticalAlignment" Value="Top"></Setter>
<Setter Property="Height" Value="23"></Setter>
<Setter Property="TextWrapping" Value="Wrap"></Setter>
</Style>
<Style x:Key="ersLabel" BasedOn="{StaticResource {x:Type Label}}" TargetType="{x:Type Label}">
<Setter Property="FontFamily" Value="Verdana"></Setter>
<Setter Property="FontSize" Value="10"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}"></Setter>
<Setter Property="HorizontalAlignment" Value="Right"></Setter>
<Setter Property="VerticalAlignment" Value="Top"></Setter>
<Setter Property="Width" Value="auto"></Setter>
</Style>
<Style x:Key="ersHeadLabel" BasedOn="{StaticResource ResourceKey=ersLabel}" TargetType="{x:Type Label}">
<Setter Property="FontSize" Value="20"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
</Style>
<Style x:Key="ersStackPanel" TargetType="{x:Type StackPanel}">
<Setter Property="Width" Value="497"></Setter>
<Setter Property="Height" Value="44"></Setter>
<Setter Property="VerticalAlignment" Value="Top"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="Margin" Value="0,10,0,0"></Setter>
</Style>
<Style x:Key="ersGrid" TargetType="{x:Type Grid}">
<Setter Property="Height" Value="44"></Setter>
</Style>
</Window.Resources>
The problem is that all elements (Label, TextBox ..) are overlapping each other, Why they are not positioning like a stack (one after another) ??
If you are using grid layout you need to define rows and columns. If u don't define them, XAML will stack them one over the other. The last element defined will be the visible one.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="A"/> // The first is assumed that it is Grid.Row="0" Grid.Column="0"
<TextBlock Grid.Row="0" Grid.Column="1" Text="B"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="C"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="D"/>
</Grid>
This will look like this:
A B
C D
In your code the problem is that you are setting elements to the second, third and fourth row, but you didn't defined the rows in the first place.
Also remember that enumeration is Zero-based (First row is actually 0).

How can I change listbox selected item background and foreground?

<Window.Resources>
<Style x:Key="ListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="{StaticResource ResourceKey=ListboxBack}"/>
<Setter Property="Foreground" Value="Green"/>
<Setter Property="Width" Value="284"/>
<Setter Property="Height" Value="332"/>
<Setter Property="Margin" Value="18,77,0,151"/>
<Setter Property="ItemTemplate" Value="{DynamicResource DataTemplate1}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0,0,0,0"/>
</Style>
<DataTemplate x:Key="DataTemplate1">
<Grid Width="276" Height="36" Background="{x:Null}" Opacity="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.069*"/>
<ColumnDefinition Width="0.931*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="recback" Padding="40,0,0,0" Text="{Binding [0], FallbackValue=Number}" Width="Auto" HorizontalAlignment="Stretch" Margin="-1.899,0,-5.334,0" Grid.Column="0" FontSize="13.333" Height="38.277" VerticalAlignment="Top" Foreground="Black" Background="{x:Null}" Opacity="1" Grid.ColumnSpan="2" />
<Rectangle HorizontalAlignment="Stretch" Height="1" Margin="3.5,0" VerticalAlignment="Bottom" Width="Auto" Fill="White" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
</Window.Resources>
<ListBox Style="{StaticResource ResourceKey=ListBoxStyle}" BorderThickness="0" x:Name="listBox1" Foreground="White" FontSize="18" d:LayoutOverrides="VerticalAlignment" BorderBrush="{x:Null}" />
I create ListBox with DataTemplate. DataTemplate contains a Rectangle and a Textblock. When I select item in ListBox I want to change TextBlock foreground and Rectangle background. Could you help me?
Use a similar to the following approach. This way you will override the default Brushes with the specified x:Key used of this ListBox Only. Perhaps you need additional or different x:Keys to override
<ListBox>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Green" />
</ListBox.Resources>
</ListBox>
By reading again your question i understand that perhaps you also need DataTriggers in your DataTemplate.
You might also try something like this Notice that Forground and BackGround should be set in the style not in TextBlock for this code to work:
<TextBlock x:Name="recback" Padding="40,0,0,0" Text="{Binding [0], FallbackValue=Number}" Width="Auto"
HorizontalAlignment="Stretch" Margin="-1.899,0,-5.334,0" Grid.Column="0" FontSize="13.333" Height="38.277"
VerticalAlignment="Top" Opacity="1" Grid.ColumnSpan="2">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="{x:Null}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

ListBox selected trigger in WPF not triggering

I setting the selected item of a list box from the code behind as follows
private void AvailableItem_Click(object sender, RoutedEventArgs e)
{
object clicked = (e.OriginalSource as FrameworkElement).DataContext;
var lbi = AvailableItem.ItemContainerGenerator.ContainerFromItem(clicked) as ListBoxItem;
lbi.IsSelected = true;
}
I have added a trigger as follows to change the selected item background color
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="Black"/>
</Trigger>
</Style.Triggers>
The problem here is that the color does not change as expected. I tried adding trigger for IsSelected value to be false and it works, but IsSelected true is not triggered. I am confused as to why this happens.
EDIT:
Here is the complete binding code:
<ListBox Height="600" Name="AvailableItem" Width="320" Grid.Column="1" ButtonBase.Click="AvailableItem_Click" Background="#00000000" BorderBrush="LightBlue" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Path = SomeText}" FontSize="14" Foreground="Black" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" Margin="0,0,0,0"/>
<Button Command="{Binding ElementName=root, Path=DataContext.SomeCommand}" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#BF000000" BorderBrush="Transparent" Foreground="White" Content="..." Width="25" Height="25" Margin="5,0,5,0">
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Yellow" />
<Setter Property="Background" Value="Red"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>

Categories