Border not lining up on a TextBlock - c#

I am working on a chat program, and I would like to have a single line separate every line of text.
Here is the XAML I am using:
<ScrollViewer Grid.Row="0" Name="ScrollBar">
<ListView HorizontalContentAlignment="Stretch"
BorderThickness="0"
IsTabStop="False"
Name="AllItems"
Background="#E4E4E4"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
PreviewMouseWheel="AllItems_PreviewMouseWheel"
ItemsSource="{Binding Messages}">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black"
BorderThickness="0, 1, 0, 0">
<TextBlock
FontSize="16"
TextWrapping="Wrap"
FontFamily="Arial"
Margin="0"
Initialized="ChatLine_Initialized"
VerticalAlignment="Center" />
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
I'm also setting the background of each line in alternating colors (this is an event handler for TextBlock's Initialize event):
static int s_curr;
void ChatLine_Initialized(object sender, EventArgs e)
{
int curr = Interlocked.Increment(ref s_curr);
if ((curr % 2) == 0)
((TextBlock)sender).Background = (SolidColorBrush)(new BrushConverter().ConvertFrom("#C8C8C8"));
else
((TextBlock)sender).Background = (SolidColorBrush)(new BrushConverter().ConvertFrom("#E4E4E4"));
}
The problem I'm running into is that the darker lines do not fill down to the border.
For example, here is how it renders:
How do I get the darker background to fill down to the border line?

Remove the border of your textblock and apply a style for the ListBox Items, this works,
<Grid>
<ScrollViewer Grid.Row="0" Name="ScrollBar">
<ListView HorizontalContentAlignment="Stretch"
BorderThickness="0"
IsTabStop="False"
Name="AllItems"
Background="#E4E4E4"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Messages}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Name="Border" BorderBrush="Black" BorderThickness="1">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock
FontSize="16"
TextWrapping="Wrap"
FontFamily="Arial"
Text="{Binding Name}"
Initialized="ChatLine_Initialized"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</Grid>
Output:

There's no need to create a ListView wrapped in a ScrollViewer and then set each alternate row a different color. A DataGrid has all this functionality built in.
This can be tweaked, but is styled to represent your screen-shot:
<DataGrid HorizontalContentAlignment="Stretch"
BorderThickness="0"
IsTabStop="False"
Name="AllItems"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Messages}"
AlternationCount="2"
HeadersVisibility="None">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="AlternationIndex" Value="0">
<Setter Property="Background" Value="#E4E4E4" />
</Trigger>
<Trigger Property="AlternationIndex" Value="1">
<Setter Property="Background" Value="#C8C8C8" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>

Related

WPF ListBoxes - change background of one ListBox based on selected items of another ListBox

I have a WPF window with two ListBoxes. The items for both are added at run time from the view model and the items for ListBox2 (SelectionMode="Multiple") are dependent on ListBox1(SelectionMode="Single") selected item.
Now, I want to update the background of the selected item for ListBox1 whenever the user selects/deselects a item in ListBox2. The background of selectedItem of ListBox1 should update if the selected item count of ListBox2 > 0.
Also, I want the background to remain regardless of the item being selected, i.e. Suppose I am on Obj 1 in ListBox1 and I select some items in ListBox2, now even if I select Obj 3 in ListBox1 the background of Obj1 should not change. I already have a hash set to store all the selected items of ListBox2 in the code behind to which the items are added/removed on selection changed event of ListBox2.
Is it possible to do this from the code behind or using the style triggers ?
Here is the code to make things a bit more clear
<Border Grid.Column="1">
<Grid>
<ListBox x:Name="ListBox1" Style="{StaticResource ListBoxStyle}" SelectionMode="Single"
SelectionChanged="ListBox1_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="ObjBorder" Height="45">
<Grid x:Name="lstItemGrid" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Height="45">
<TextBlock x:Name="Text" Text="{Binding LB1Name}" />
</Border>
<Path Grid.Column="1" x:Name="CheckMark" Style="{StaticResource CheckStyle}">
</Path>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsVisible, ElementName=CheckMark}" Value="Visible">
<Setter Property="Background" TargetName="lstItemGrid" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
<Border Grid.Column="2" BorderThickness="0" VerticalAlignment="Stretch">
<Grid>
<ListBox x:Name="ListBox2" Style="{StaticResource ListBoxStyle}" SelectionMode="Multiple" SelectionChanged="ListBox2_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="ObjBorder" BorderBrush="Transparent" Height="45">
<Grid x:Name="lstItemGrid" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Height="45">
<TextBlock x:Name="Text" Text="{Binding LB2Name}" />
</Border>
<Path Grid.Column="1" x:Name="CheckMark" Style="{StaticResource CheckStyle}"></Path>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter Property="Background" TargetName="lstItemGrid" Value="Red"/>
<Setter Property="Visibility" TargetName="CheckMark" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>

WPF DataGrid Grouped Rows in Expander adds extra column on right side, disappears when all expanders are closed

Another WPF DataGrid-related question.
I have a DataGrid whose rows are grouped, and each group is underneath an Expander control. There are two columns per row. By default, I have all the expanders opened. The second column's width is set to "*", and row headers have already been turned off.
When I close all the expanders, the layout changes the tiniest bit, shifting the expander controls to the left a little. When I open any one of the expanders, they shift the tiniest bit to the right. I also notice that when an expander is open, the column headers show an additional column on the right side, which makes the horizontal scroll bar appear.
How can I adjust the datagrid declaration to make this additional column not exist/appear when an expander is open?
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled" >
<DataGrid AutoGenerateColumns="False"
ItemsSource="{Binding Path=MyCollection}"
GridLinesVisibility="None"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserSortColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
HeadersVisibility="Column">
<DataGrid.Resources>
<ResourceDictionary>
<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="{x:Type DataGridRow}" TargetType="{x:Type DataGridRow}">
<Setter Property="Margin" Value="4" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</DataGrid.Resources>
<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 Margin="4"
IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal"
Margin="4">
<TextBlock FontWeight="Bold"
FontSize="14"
Text="{Binding Path=Name}" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto">
...
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*">
...
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</Grid>
The DataGrid itself has a built in scrollviewer so the outside one isn't needed. I think it is the DataGrid's scrollviewer that is causing your issue. Try getting rid of the outside ScrollViewer and add the attributes to the DataGrid, like this:
<DataGrid AutoGenerateColumns="False"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
...
>
...
</DataGrid>
If you need the outside scrollviewer for some reason, keep it but still disable the DataGrid's HorizontalScrollBarVisibility.
This is part hack, part real answer I think.
Hack part: In order to get the horizontal scroll bar to not show up, I simply disabled it in the DataGrid declaration. Then, to ensure that the column didn't get shaved off a little on the right side, I set row margin and padding in the style I used to turn off selection color.
Real part: Setting the vertical scrollbar to always show works properly as long as the height of the second row of the outtermost grid is set to "*" (asterisk). This ensures the DataGrid will use the proper amount of space when an expander is opened and there are too many rows to show.
The final DataGrid declaration looks like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="Import Data Mappings"
FontWeight="Bold"
HorizontalAlignment="Center"
Margin="4"
Padding="4"
Grid.Row="0" />
<DataGrid AutoGenerateColumns="False"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=MyGroupedCollection, Mode=OneWay}"
HeadersVisibility="Column"
Grid.Row="1"
... >
<DataGrid.Resources>
<ResourceDictionary>
<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="{x:Type DataGridRow}" TargetType="{x:Type DataGridRow}">
<Setter Property="Margin" Value="0,4,0,4" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</DataGrid.Resources>
<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 Margin="4"
IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal"
Margin="4">
<TextBlock FontWeight="Bold"
FontSize="14"
Text="{Binding Path=Name}" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.HeaderTemplate>
...
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock .../>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.HeaderTemplate>
...
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DockPanel LastChildFill="True">
<Button Style="{DynamicResource ResourceKey=MyButtonStyle}"
Content="Button Text"
Command="{Binding Path=MyButtonCommand}"
DockPanel.Dock="Left"/>
<ComboBox Margin="4"
Padding="4"
SelectedItem="{Binding Path=MySelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=MyAvailableFields}"
DockPanel.Dock="Left">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="{Binding Path=MyDisplayName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DockPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>

Adjust Selected ListViewItem TextBlock Style

I am having a strange issue. I am not sure if this is a bug, or if I am simply misunderstanding something as I am fairly new to WPF (Probably the latter).
In my project, I have a ListView that displays items in a similar fashion to that seen of Windows Explorer using Icon view. I have outlined a control template that consists of a an Image element, and a TextBlock element below it. My goal is to adjust the maximum height of the TextBlock when the ListViewItem is selected. This is so the name of the Items will adjust from being trimmed with an ellipsis to showing the full name of the item.
When the item is selected however, instead of adjusting the maximum height of only the selected item's TextBlock, it adjusts all TextBlocks for each item whether it is actively selected or not.
I have researched for an answer, but have not found anything similar to this particular issue. This link is a similar concept, but without my problem.
WPF - ListView Item on Selected change Font size
Some of my other methods have consisted of one ControlTemplate with triggers for the style changes, or ItemContainerStyle instead of explicitly a ControlTemplate, which all seemed to give the same undesired result.
How can I achieve this functionality? Is it possible with ControlTemplate?
Here is some of my XAML code:
ListView
<ListView x:Name="ItemViewer">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Margin="10"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="10"/>
<Setter Property="Template" Value="{StaticResource ListViewItemNormal}"/>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Template" Value="{StaticResource ListViewItemSelected}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
ControlTemplates
<ControlTemplate x:Key="ListViewItemNormal" TargetType="{x:Type ListViewItem}">
<Border x:Name="ItemBoxBorder" Background="Transparent">
<Grid HorizontalAlignment="Left" MinHeight="90"
Margin="5"
MaxWidth="90"
Width="90"
x:Name="ItemBox">
<StackPanel>
<Image HorizontalAlignment="Center"
VerticalAlignment="Top"
Source="{StaticResource NewImage}"
Width="64" Height="64"/>
<TextBlock x:Name="ItemDescription"
Text="{Binding Path=Name}"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
TextWrapping="Wrap"
MaxWidth="90"
MaxHeight="30"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
<Grid.ToolTip>
<ToolTip Content="{Binding Path=Name}"/>
</Grid.ToolTip>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="False"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter TargetName="ItemBoxBorder" Property="Background" Value="{StaticResource HighlightMouseHoverColorBrush}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ListViewItemSelected" TargetType="{x:Type ListViewItem}">
<Border x:Name="ItemBoxBorder" Background="{StaticResource SelectedItemBrush}"
BorderBrush="{StaticResource HighlightBorderColorBrush}"
BorderThickness="1">
<Grid HorizontalAlignment="Left" MinHeight="90"
Margin="5"
MaxWidth="90"
Width="90"
x:Name="ItemBox">
<StackPanel>
<Image HorizontalAlignment="Center"
VerticalAlignment="Top"
Source="{StaticResource NewImage}"
Width="64" Height="64"/>
<TextBlock x:Name="ItemDescription"
Text="{Binding Path=Name}"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
TextWrapping="Wrap"
MaxWidth="90"
MaxHeight="125"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
<Grid.ToolTip>
<ToolTip Content="{Binding Path=Name}"/>
</Grid.ToolTip>
</Grid>
</Border>
</ControlTemplate>
EDIT
Here is an example of the issue with ms_dos's implementation.
This image shows I have the item with a short description selected. This is the height all items should remain if they are not selected.
In this image, you'll see the item with the long description is selected. However, both items extend their height, but only the selected one should grow.
You don't need two separate control templates for this. Just take the ItemContainerStyle property of the ListView and use a control template like this:
<ListView x:Name="ItemViewer">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Margin="10" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border x:Name="ItemBoxBorder"
Background="Green"
BorderThickness="1"
VerticalAlignment="Top">
<Grid HorizontalAlignment="Left"
MinHeight="90"
Margin="5"
MaxWidth="90"
Width="90"
x:Name="ItemBox">
<StackPanel>
<Image HorizontalAlignment="Center"
VerticalAlignment="Top"
Width="64"
Height="64" />
<TextBlock x:Name="ItemDescription"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
TextWrapping="Wrap"
Text="{Binding}"
MaxWidth="90"
MaxHeight="125"
TextTrimming="CharacterEllipsis" />
</StackPanel>
<Grid.ToolTip>
<ToolTip Content="{Binding Path=Name}" />
</Grid.ToolTip>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="true">
<Setter TargetName="ItemBoxBorder"
Property="Background"
Value="Red" />
<Setter TargetName="ItemDescription"
Property="TextElement.FontSize"
Value="20" />
<Setter TargetName="ItemBoxBorder"
Property="Height"
Value="135" />
</Trigger>
<Trigger Property="IsSelected"
Value="false">
<Setter TargetName="ItemBoxBorder"
Property="Height"
Value="90" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Take a look at the ControlTemplate.Triggers section. Basically you use the Trigger property to control which property the trigger should handle... in our case the IsSelected from the ListView. And with the Setter you define the property and the value for the changes of the ListViewItem control. The TargetName of the Setter refers to the x:Name of the control which you define in the ControlTemplate section.
I hope this example helps you with your problem!
Greets
ms_dos

How to change itemsControl stackpanel background color

Says I have a list of 10 items someList, I will show them on my page via itemsControl like below:
<ItemsControl DataContext="{Binding [someViewModel]}"
BorderBrush="Black"
ItemSource="{Binding someList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" Background="Green">
<StackPanel MouseDown="{Binding Path=DataContext.someCommand,
RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}}"
Command Parameter="{Binding someID}">
<TextBlock Text="{Binding something}">
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I do able to trigger someCommand method and I do able to pass in someID as input parameter. Now I'm wondering how to update the stackPanel background color, making it looks like "selected". Meaning now all item will have a green background, when I click on one of the stackpanel, that stackpanel should change background to red and change others back to green
If you want to use ItemsControl you can change ItemTemplate to RadioButton with custom ControlTemplate that will include Border which Background would change to Red when IsChecked == true:
<ItemsControl DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding something}" GroupName="radioGroup">
<RadioButton.Template>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="Green" x:Name="PART_Border">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="PART_Border" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
However I don't see a reason why you cannot use ListBox with SelectionMode=Single (default value) and change Template of ListBoxItem:
<ListBox DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Background="Green" x:Name="PART_Border">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="PART_Border" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
or even do something like this, without changing Template:
<ListBox DataContext="{Binding [someViewModel]}" BorderBrush="Black" ItemSource="{Binding someList}">
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Green"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
In WPF it's generally much easier to pick a control that has functionality that you need and style it to look like you want then do this the other way round
why not do something like this
<DataTemplate>
<Border BorderThickness="1" Background="Green" x:Name="MyBorder">
<StackPanel MouseDown="{Binding Path=DataContext.someCommand,
RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}}"
Command Parameter="{Binding someID}">
<TextBlock Text="{Binding something}">
</StackPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="true">
<Setter TargetName="MyBorder" Property="Background" Value="Black" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

WPF listbox empty item template not showing

I am try to list some data in WPF listbox control. It is the first time I am using DataTemplate in WPF. Everything is working fine except when there is no data it is not showing 'No items to display'. Below is my code.
<ListBox Name="itemsCtrl" Background="#FFE5E5E5" BorderBrush="{x:Null}" SelectionChanged="itemsCtrl_SelectionChanged" Style="{StaticResource ListStyle}">
<ListBox.Resources>
<!-- Set SelectedItem Background here -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#C2C2C2"/>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,
RelativeSource={RelativeSource
Self}}"
Value="True">
<Setter Property="Background"
Value="#C2C2C2" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ListBox" x:Key="ListStyle" BasedOn="{StaticResource {x:Type ListBox}}">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Items.Count}"
Value="0"
>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock>No items to display</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Cursor="Hand" Name="hoverDataTemplate" Orientation="Horizontal" Width="370" VerticalAlignment="Top" Height="40" HorizontalAlignment="Left" >
<Label VerticalContentAlignment="Center" HorizontalAlignment="Left" Padding="15,5,5,5" Width="330" Content="{Binding Path=EVENT_TITLE}" FontSize="12"/>
<Image Height="28" Source="/pr;component/Images/black_next.png" Stretch="Fill" Width="28" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And I am binding data source as shown below.
itemsCtrl.ItemsSource = dao.SelectDataTable(cmd).DefaultView;
When I set the style property of ListBox as ListStyle it is throwing an error
'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '292' and line position '22'.
Can anybody point out how to make it correct?
Thanks in advance.
i have used below code and it's work fine
my xaml code
<ListBox Grid.ColumnSpan="2" Grid.Row="1" Height="32" HorizontalAlignment="Left" Margin="160,2,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" Style="{StaticResource Dhaval}"/>
Style look like
<Style x:Key="Dhaval" TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}" Value="0">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock>No items to display</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>

Categories

Resources