ListBox selected trigger in WPF not triggering - c#

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>

Related

WPF How to bind data between user control and mainview?

I'm trying to transfer list from mainview to user control. My solution doesn't work. Everything works fine except for the transferring the list.
My user control:
public List<Song> ListIWantTransferFromMainviewToUsercontrol = new List<Song>();
public View_Playlist()
{
InitializeComponent();
ToPlayList.ItemsSource = ListIWantTransferFromMainviewToUsercontrol;
ToPlayList.Items.Refresh();
}
My mainview:
var i = Playlists_ListBox.Items.IndexOf(Playlists_ListBox.SelectedItem);
string y = Playlists[i].Title;
var z = Playlists[i].Songs;
View_Playlist view_Playlist = new View_Playlist
{
ListIWantTransferFromMainviewToUsercontrol = z
};
this.contentControl.Content = view_Playlist;
I should click on item in listbox shown by mainview and run this code on click. Has anyone working solution for my problem? Thanks for reply.
User control XAML, listbox part:
<ListBox Name="ToPlayList" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="4" Background="{x:Null}" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="BorderBrush" Value="BlanchedAlmond" />
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Gray" />
<Setter Property="BorderThickness" Value="2" />
</Trigger>
<Trigger Property="IsMouseCaptured" Value="True">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="Gray" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="205"/>
<ColumnDefinition Width="90" />
<ColumnDefinition Width="90" />
<ColumnDefinition Width="35" />
</Grid.ColumnDefinitions>
<CheckBox/>
<TextBlock Grid.Column="1" Text="{Binding SongTitle}" Foreground="White"/>
<TextBlock Grid.Column="2" Text="{Binding SongArtist}" Foreground="White"/>
<TextBlock Grid.Column="3" Text="{Binding SongDate}" Foreground="White"/>
<TextBlock Grid.Column="4" Text="{Binding Duration}" Foreground="White"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I solved it by parameter. It isn't ideal, but working.

TextBox validation sets Button border to red

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>

Button inside button MVVM. How to hit the inner button?

I have a 'plus' button (see image) inside big button. How execute command of 'plus' button.
'plus' button in my example is CreateNewFolderButton(first style) and locate in Grid.Column=2 of MakeNewFolderButton(second style).
Tinkering with WindowChrome.IsHitTestVisibleInChrome and IsHitTestVisible doesn't help.
How to get access to the 'plus' button and execute its command with MVVM?
<Style x:Key="CreateNewFolderButton" TargetType="{x:Type Button}" BasedOn="{StaticResource HoverLess}">
<Setter Property="ToolTip" Value="Create Folder"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="IsHitTestVisible" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Grid >
<Ellipse Width="{StaticResource WidthNavigationAndCreation}" Height="{StaticResource HeightNavigationAndCreation}" />
<Ellipse Width="{StaticResource WidthNavigationAndCreation}" Height="{StaticResource HeightNavigationAndCreation}" x:Name="image" >
<Ellipse.Fill>
<ImageBrush ImageSource="{DynamicResource AddFolder}" />
</Ellipse.Fill>
</Ellipse>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" TargetName="image" Value="{DynamicResource IBAddFolderMouseOver}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MakeNewFolderButton" TargetType="{x:Type Button}" BasedOn="{StaticResource FolderFileButtons}">
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0 0 0 0.5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Width="{StaticResource WidthFolderAndFilesIcon}"
Height="{StaticResource HeightFolderAndFilesIcon}" Source="/Images/FolderAndFiles/BlackEmptyFolder48x48.png"/>
<TextBox Grid.Column="1" Style="{StaticResource TextBoxEnterFileCreation}"
Tag="New Folder Name"
Text="{Binding RelativeSource={RelativeSource AncestorType=Window},
Path=DataContext.NewFolderName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="2" Style="{StaticResource CreateNewFolderButton}"
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.MakeFolder}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="{StaticResource ButtonBackgroundMouseOver}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
'Plus' button inside big button
As I wrote in comment this code works:
<Button Content="Outer button" Command="{Binding TestCmd}">
<Button.Template>
<ControlTemplate TargetType="ButtonBase">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="AUTO" />
<ColumnDefinition Width="AUTO" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="LABEL CONTENT" Foreground="BlueViolet"/>
<Button Grid.Column="1" Content="INNER BUTTON" Command="{Binding TestCmd2}"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
So if you press "INNER BUTTON" the TestCmd2 being executed and if you click a "LABEL CONTENT" the TestCmd being executed.

Alteration Color Change for Listbox

I have a listbox and I want to change the color of every other row. I have tested the following code, but the colors are not changing. Am I missing something?
<ListBox Height="250" BorderThickness="0" ItemsSource="{Binding Path=Results}" AlternationCount="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" FontFamily="Sagoe UI" FontSize="14" Text="{Binding FirstName, StringFormat='User: {0}'}" Padding="2" />
<TextBlock Grid.Column="1" FontFamily="Sagoe UI" FontSize="14" Text="{Binding Company, StringFormat='Company: {0}'}" Padding="2" />
<TextBlock Grid.Column="2" FontFamily="Sagoe UI" FontSize="14" Text="{Binding Dept, StringFormat='Department: {0}'}" Padding="2" >
</TextBlock>
</Grid>
</DataTemplate>
<ListBox.ItemTemplate>
Here is my style and the closing tags for resoruces and dictionary
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#19f39611"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#19000000"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
Wow Forgot I was using RadListBox, so the answer is change the opening and closing Control Tags To
<telerik:RadListBox></telerik:RadListBox>
Then
<Style TargetType="{x:Type telerik:RadListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#19f39611"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#19000000"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>

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>

Categories