Change background color of a WPF ItemTemplate - c#

I have to change Background color of an ItemTemplate of a ListBox, depending the value of a boolean.
Here is my ListBox :
<ListBox Name="itemListBox"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="itemListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="200">
<TextBlock FontSize="10"
FontWeight="Bold"
VerticalAlignment="Center"
Text="{Binding Path=Value.DocID}" />
<TextBlock FontSize="10"
VerticalAlignment="Center"
TextWrapping="Wrap"
Text="{Binding Path=Value.Serial}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If the user delete an Item, I want to show him in grey backrgound.
Precision : The ListBox is binded to a Dictionnary, that contains a boolean value "IsDeleted".
Sorry for the poor English.
Thank you

You could use an ItemContainerStyle with a DataTrigger:
<ListBox Name="itemListBox" ScrollViewer.VerticalScrollBarVisibility="Visible" SelectionChanged="itemListBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Value.IsDeleted}" Value="True">
<Setter Property="Background" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="200">
<TextBlock FontSize="10" FontWeight="Bold" VerticalAlignment="Center" Text="{Binding Path=Value.DocID}" />
<TextBlock FontSize="10" VerticalAlignment="Center" TextWrapping="Wrap" Text="{Binding Path=Value.Serial}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Make sure that the class with the IsDeleted property implements the INotifyPropertyChanged interface correctly if you intend to set the property dynamically and want the background to get updated accordingly.

Related

LostFocus does'nt work TextBox when selecting a TreeviewItem

Hi I need to solve a problem between the TextBox and the treeview. When I select the TreeView after the TextBox I don't receive the LostFocus Event (for the TextBox) why?
I have tried to play a lot with Focusable and the focusableManager but .... it didn't helped me.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Visibility="{Binding VariableA, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToHiddenConverter}}
<TextBox Width="78" FocusManager.IsFocusScope="True"
PreviewTextInput="HatchingDistanceBox_PreviewTextInput"
Name="TextBoxAWhoShouldLostFocus" BorderThickness="0.5"
BorderBrush="White" MinHeight="30" Height="30" Text="{Binding SelectedFamille.VariableA}"
utilities:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text">
</TextBox>
<TreeView Name="TreeView_After" ItemsSource="{Binding FirstGeneration}" Focusable="True" Grid.ColumnSpan="3" Grid.Row="2" Grid.Column="0" AllowDrop="True" Background="#282828" Margin="15, 0,0,0" >
<TreeView.Style>
<Style TargetType="{x:Type TreeView}">
<EventSetter Event="GotFocus" Handler="TreeViewItem_GotFocus"></EventSetter>
</Style>
</TreeView.Style>
<i:Interaction.Behaviors>
<utilities:TreeViewSelectionBehavior SelectedItem="{Binding SelectedFamille}"/>
</i:Interaction.Behaviors>
<TreeView.Resources>
<DataTemplate x:Key="NormalTemplate">
<StackPanel Orientation="Horizontal" Name="StrategyNamePanel" Mouse.PreviewMouseDown="StrategyNamePanel_MouseDown" Width="200" Background="#282828" Focusable="True" FocusManager.IsFocusScope="True">
<TextBox Name="StrategyNameBox" FontWeight="Normal" FocusManager.IsFocusScope="True" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=Explicit}" MinHeight="30" Height="30" BorderThickness="0" utilities:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"></TextBox>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="EditTemplate">
<StackPanel Orientation="Horizontal" Name="NamePanel" Focusable="True" Mouse.PreviewMouseDown="NamePanel_MouseDown" Width="200" Background="{StaticResource DarkGrey}" FocusManager.IsFocusScope="True">
<TextBox Name="NameBox" FontWeight="Normal" BorderBrush="{StaticResource DarkOrange}" FocusManager.IsFocusScope="True" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=Explicit}" MinHeight="30" Height="30" utilities:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text" ></TextBox>
</StackPanel>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="GotFocus" Handler="TreeViewItem_GotFocus"></EventSetter>
<EventSetter Event="TreeViewItem.DragOver" Handler="TreeView_After_DragOver"/>
<EventSetter Event="TreeViewItem.Drop" Handler="TreeView_After_Drop"/>
<EventSetter Event="TreeViewItem.MouseMove" Handler="TreeView_After_MouseMove"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
The LostFocus from the textbox work when I click everywhere except in the TreeView
2) The lostFocus work if I first select a parent in the treeView and then a Treeview Item.
3)When I first select a treeViewItem and Then an Another treeViewItem there is no more LostFocus Event.
Why????

One SelectedItem For Multiple Wpf Controls

I have a list box Bound to XML data correctly , but i have multiple Tree Views inside this listbox which you can select item for every one of them!
i want single item selecting from all of these tree views. which every one of those are inside an unique expander.
if you look at my xml data ,consider i have 2 groups inside xml , i can select item for both of those groups in listbox which now they are different treeviews in my ui , and i want single item selecting for all this listbox items.
<ListBox Background="Transparent" BorderThickness="0" SelectedValue="{Binding SelectedMenuValue,Mode=TwoWay}" ItemsSource="{Binding Path=Items,Source={StaticResource XmlSourceMenu}}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type revoxml:Group}">
<Expander Header="{Binding Title}">
<TreeView ItemsSource="{Binding Menus}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding}">
<StackPanel Orientation="Horizontal" Margin="10 0">
<fa:ImageAwesome Height="30" Width="30" VerticalAlignment="Center" Margin="5" Icon="{Binding Icon}" />
<TextBlock Text="{Binding Title}" Height="30" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Expander>
</DataTemplate>
<DataTemplate DataType="{x:Type revoxml:SubMenu}">
<StackPanel Orientation="Horizontal" Margin="10 0">
<fa:ImageAwesome Height="30" Width="30" VerticalAlignment="Center" Margin="5" Icon="{Binding Icon}" />
<TextBlock Text="{Binding Title}" Height="30" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
</DataTemplate>
</ListBox.Resources>
</ListBox>
for easier understanding data for this listbox comming from xml file like this :
<MainMenu>
<Group Title="title">
<SubMenu Icon="Inbox" Title="inbox" Tag="38"/>
<SubMenu Icon="CommentingOutline" Title="New Message" Tag="37"/>
<SubMenu Icon="Tachometer" Title="Archive" Tag="39"/>
<Menu Icon="CartArrowDown" Title="purchases" >
<SubMenu Icon="CartArrowDown" Title="new" Tag="26"/>
<SubMenu Icon="CartPlus" Title="list" Tag="28"/>
</Menu>
</Group>
<SubMenu Icon="InfoCircle" Title="info" Tag="6000" />
<SubMenu Icon="Close" Title="close" Tag="0"/>
</MainMenu>
this should solve it ! but you need to implement your own selected item, or you could change groupboxes to expander and items control to tree view to match your code
<Style TargetType="StackPanel" x:Key="HoverStackPanelStyle">
<Setter Property="Background" Value="Transparent"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
<ScrollViewer>
<HeaderedItemsControl Background="Transparent" ItemsSource="{Binding Path=Items,Source={StaticResource XmlSourceMenu}}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type revoxml:SubMenu}">
<StackPanel Orientation="Horizontal" Margin="10 0" Style="{StaticResource HoverStackPanelStyle}">
<fa:ImageAwesome Height="30" Width="30" VerticalAlignment="Center" Margin="5" Icon="{Binding Icon}" />
<TextBlock Text="{Binding Title}" FontFamily="{StaticResource nazanin}" Height="30" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate DataType="{x:Type revoxml:Menu}" ItemsSource="{Binding Menus}">
<GroupBox Header="{Binding Title}" Margin="0 5">
<ItemsControl ItemsSource="{Binding Menus}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type revoxml:SubMenu}">
<StackPanel Name="StackPanel" Orientation="Horizontal" Margin="10 0" Style="{StaticResource HoverStackPanelStyle}">
<fa:ImageAwesome Height="30" Width="30" VerticalAlignment="Center" Margin="5" Icon="{Binding Icon}" />
<TextBlock Text="{Binding Title}" FontFamily="{StaticResource nazanin}" Height="30" VerticalAlignment="Center" Margin="5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</GroupBox>
</HierarchicalDataTemplate>
</ItemsControl.Resources>
</HeaderedItemsControl>
</ScrollViewer>

Style doesn't apply to StackPanel items in ListView - Windows Universal

I have created a listview with databinding and a "Itemstemplate" which takes a "Datatemplate" where I have a Stackpannel but the style doesn't apply to the stackpannel, there is no space between the textblocks in the stackpannel:
<ListView Grid.Row="1" DataContext="{Binding Source={StaticResource ViewModel}}" ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Gray" >
<StackPanel.Resources>
<Style TargetType="TextBlock" x:Key="margintextblock">
<Setter Property="Margin" Value="10,0,0,0"/>
</Style>
</StackPanel.Resources>
<TextBlock Style="{StaticResource listviewtextblock}" Text="{Binding Path=Firstname}" Foreground="Gold"></TextBlock>
<TextBlock Style="{StaticResource listviewtextblock}" Text="{Binding Path=Lastname}" Foreground="Black"></TextBlock>
<TextBlock Style="{StaticResource listviewtextblock}" Text="{Binding Path=Id}" Foreground="OrangeRed"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
So what's wrong?
You have to remove x:Key="margintextblock" because of this the style doesn't apply automatically to the TextBlocks
By setting the x:Key property on a style, you are telling WPF that you only want to use this style when you explicitly reference it on a specific control.
Take a look on this tutorial
EDITED
And you also have another problem - you are setting style for you TextBlocks Style="{StaticResource listviewtextblock}"
In this case what you have to do is inherit StackPanel TextBlock style from listviewtextblock style
<StackPanel.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource listviewtextblock}">
<Setter Property="Margin" Value="10,0,0,0"/>
</Style>
</StackPanel.Resources>
And remove style Style="{StaticResource listviewtextblock}" from TextBlocks
you code should looks like this
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Gray" >
<StackPanel.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource listviewtextblock}" >
<Setter Property="Margin" Value="10,0,0,0"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="{Binding Path=Firstname}" Foreground="Gold"></TextBlock>
<TextBlock Text="{Binding Path=Lastname}" Foreground="Black"></TextBlock>
<TextBlock Text="{Binding Path=Id}" Foreground="OrangeRed"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>

Datagrid Grouping displaying the Field value that you are grouping on as Header

I am trying to Group Items in a DataGrid and display the value of the Field it is grouping on in the header. For example:
Ford - 3 items
F150
Mustang
Chevy - 2 items
Every example I have looked at shows me the exact same thing which doesn't seem to work at all for me.
<DataGrid IsSynchronizedWithCurrentItem="True" SelectionUnit="FullRow" RowHeaderWidth="0" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" IsReadOnly="True" ItemsSource="{Binding View}" SelectedItem="{Binding Path=SelectedContingency, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" >
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" wtf " />
<TextBlock Text="{Binding Path=Description, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
<TextBlock Text="{Binding Path=ItemCount}"/>
<TextBlock Text=" Items" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
Also had this for a while but it made no difference
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Description}" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
Instead of getting a description here I just get ( wtf 3 items ) etc. I've tried different fields and nothing. I've tried every variation I can think of for the field in the exapander header.
What magic is required to make this common feature function?
The answer to this is that in the examples they bind to the field name. So when you see in the examples:
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name"} />
<TextBlock Text="{Binding Path=ItemCount}"/>
<TextBlock Text=" Items" />
</StackPanel>
</Expander.Header>
You might assume as I did that "Name" is used because thats also the field they chose to bind to. This is not the case. "Name" is the actual property on the GroupItem that you are binding to that has the value.
So no matter what Field you are grouping on, you always display that field by binding to "Name" on the GroupItem.

how to select using a wrap panel as the item panel for listview

I want to show a list of items horizontally and be able to select from this list of items - I have tried using a listview and changing the item template per some posts on stack and I have this:
<ListView Height="Auto" HorizontalAlignment="Left" Margin="24,0,0,0" Name="MachinesListView" VerticalAlignment="Top" Width="1455" Background="#FFF0F0F0" ItemsSource="{Binding Machines}" BorderBrush="#FFF0F0F0" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="MachinesListView_SelectionChanged">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="175"/>
<Setter Property="Width" Value="275"/>
<Setter Property="Margin" Value="5,5,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Gray" BorderThickness="2" CornerRadius="10">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Machine.MachineId}" TextAlignment="Center" Width="Auto" Foreground="#FF639A70" FontSize="19"/>
<TextBlock Text="{Binding Machine.Name}" TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" />
<Image Source="/URM;component/Images/slot_machine-512.png" Height="60" Width="60" />
<TextBlock Text="{Binding Machine.Description}" TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0"/>
<TextBlock TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0">
<Run Text ="Actual: "/>
<Run Text ="{Binding Actual, StringFormat=' {0:c}'}"/>
</TextBlock>
<TextBlock TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0">
<Run Text ="OverShort: "/>
<Run Text ="{Binding OverShort, StringFormat=' {0:c}'}"/>
</TextBlock>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
This works well...I get the overall look and feel that I want from this but only selecting the first item causes the selectionchanged event to fire...
I thought about implementing the items as buttons instead but I thought there might be a more proper way of dealing with this.
Set Background to Transparent on outer most border of ControlTemplate.
<Border BorderBrush="Gray" Background="Transparent"
BorderThickness="2" CornerRadius="10">
By default it's {x:Null} which is not responsive to mouse events.
You will see that item gets selected only in case you click over image
or any control present in template but when you click on empty area
within border, selectionChange event doesn't fire since it is
unresponsive to mouse events (specifically MouseClick in your case). Setting background to Transparent will make it responsive to all mouse events.
Refer to this for more details - {x:Null} Vs. Transparent.

Categories

Resources