Styling a Selected ListBoxItem - c#

EDIT:
<Window x:Class="test_project.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:test_project"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="White" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Yellow" Opacity="0.6" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="White" />
</ListBox.Resources>
<ListBox.Items>
<ListBoxItem Content="Hello"/>
<ListBoxItem Content="Hello"/>
</ListBox.Items>
</ListBox>
</Grid>
</Window>
I want to Style a ListBoxItem so that it has a blue background with white text when selected. I've looked at many answers online and they all seem to give contradicting opinions, none of which have worked for me so far. Here is my ListBox:
<ListBox Grid.Row="1" Margin="5" ItemContainerStyle="{StaticResource BlueItemStyle}"
BorderBrush="#06658D"
ItemsSource="{Binding UsersView}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is the Style that I have used so far and it achieves nothing:
<!--ListBoxItem-->
<Style TargetType="{x:Type ListBoxItem}" x:Key="BlueItemStyle">
<Setter Property="Height" Value="40"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#06658D"/>
</Trigger>
</Style.Triggers>
</Style>
However this does not Style the ListBoxItem in any way. Simply put, my question would be the simplest way to Style a selected ListBoxItem so the ListBox looks like this:

This solution does not work on Windows 10, which means it's no longer suitable at all, going forward. Thanks, Microsoft.
To the best of my knowledge, that's going to have to mean replacing the ListBoxItem control template. Two questions addressing that case:
WPF. ListBox item style
https://stackoverflow.com/a/35810145/424129
You can't change the selected item background color that way; the Background property of the ListBoxItem doesn't change for the selection state. Instead, ListBoxItem's default control template uses Background for unselected, and has a trigger which replaces the actual background brush of some template child with {DynamicResource {x:Static SystemColors.HighlightBrushKey}} when IsSelected is true.
You could do the same with a child of your DataTemplate, or you could replace the Template but it's easier just to override the resource instead.
You can override the same resource globally as well, for a consistent look.
<ListBox
Grid.Row="1"
Margin="5"
ItemContainerStyle="{StaticResource BlueItemStyle}"
BorderBrush="#06658D"
ItemsSource="{Binding UsersView}"
>
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#06658D" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="White" />
<!--
The default inactive selection color in Win7 is much too pale for my taste;
our older users are unable to distinguish it from white on most monitors.
-->
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#06658D" Opacity="0.6" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="White" />
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Related

How to get ControlTemplate not to override DataTemplate?

Similar to gmail's Select button, I wanted to create a ComboBox for the ListView which allows the user to quickly select entries of their choosing (ex. All, None, Read, Unread). However, the selected value would display a tri-state CheckBox equivalent to All, Some, or None of the entries being selected. I succeeded in doing so. Below is the xaml for an example Window utilizing this feature(*):
<Window x:Class="WPFTest.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfTest="clr-namespace:WPFTest.ViewModels"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest.Models"
mc:Ignorable="d" Title="WPF Test" Height="221.256" Width="605"
d:DataContext="{d:DesignInstance wpfTest:MainWindowViewModel, IsDesignTimeCreatable=True}"
prism:ViewModelLocator.AutoWireViewModel="True" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/WPFTest;Component/Resources/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ListView
ItemsSource="{Binding Entries}"
SelectedValue="{Binding SelectedEntry}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ScrollViewer.CanContentScroll="True"
SelectionMode="Single"
Margin="10">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox
IsChecked="{Binding Selected}"
Command="{Binding DataContext.RowSelectedCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
HorizontalAlignment="Center"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
ItemTemplateSelector="{DynamicResource itemTemplateSelector}"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
VerticalAlignment="Stretch"
Width="44"
Height="34"
FontSize="20"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn
Width="Auto"
DisplayMemberBinding="{Binding Type, Mode=OneWay}"
Header="Type"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Recently I was asked to make a style for every ComboBox on our screens - changing their backgrounds. Because I'm on Windows8, setting the Background alone isn't enough. Using this tutorial I was able to create the ControlTemplate to get the correct behavior, with one minor error fix:
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="True"/>
<!-- Comment out the following, it throws an error. -->
<!--<Condition>
<Condition.Value>
<sys:Boolean>False</sys:Boolean>
</Condition.Value>
</Condition>-->
</MultiTrigger.Conditions>
And usage:
<Style
TargetType="{x:Type ComboBox}">
...
<Setter
Property="Template"
Value="{StaticResource ComboBoxStyle1}" />
</Style>
This successfully styles the ComboBox Background. However, revisiting the former screen, I noticed that this breaks my gmail-like display.
How can I get this ControlTemplate and the dynamic DataTemplate to cooperate?
(*) ViewModels and Models can be provided if necessary for a solution. Or see full working example.
I'm not sure why you doing so complicated ComboBox - you defined ItemTemplateSelector twice...
Ok - here is my 2 cents: ComboBox is lookless control. It based on ControlTemplate target type = ComboBox. Inside ComboBox ControlTemplate you will find ContentPresenter. Whatever coming into Content of ContentPresenter could be styled with DataTemplate. Generally - when you define DataTemplate it wrap only ContentPresenter or ItemsPresenter for range based controls - not the whole ControlTemplate obviously.
So if you want to change 'Selected' template for ComboBox is ok but all other data should be defined via DataTemplate for this type {x:Type local:SomeType} that will be used by ComboBox.
Also - consider using #galakt suggestion: use Style with TargetType - it easy to read, refactor, find, understand...
Color the Background
As per the OP, following this tutorial, you generate the ControlTemplate.
To do this, you can right-click on the ComboBox element in design mode
in Visual Studio 2012 or 2013 and select the “Edit template” option
and then the “Edit a copy…” option.
Again note the bug fix from the OP. Changing the background can then be done by:
<Border
x:Name="templateRoot"
BorderBrush="#FFACACAC"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
Background="{StaticResource MyComboBackgroundBrush}"> <!-- option 1 -->
<!-- <Border.Background> -->
<!-- option 2 -->
<!-- <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="#FFE5E5E5" Offset="1"/>
</LinearGradientBrush>-->
<!-- option 3 -->
<!-- <SolidColorBrush Color="Yellow"/> -->
<!-- </Border.Background>
<Border x:Name="splitBorder" BorderBrush="Transparent" BorderThickness="1" HorizontalAlignment="Right" Margin="0" SnapsToDevicePixels="True" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path x:Name="Arrow" Data="F1M0,0L2.667,2.66665 5.3334,0 5.3334,-1.78168 2.6667,0.88501 0,-1.78168 0,0z" Fill="#FF606060" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
</Border> -->
</Border>
Interact with the DataTemplate
In the resource file, following the above instructions, you declared:
<ControlTemplate x:Key="ComboBoxControlTemplateBasic" TargetType="{x:Type ComboBox}">
...
<ContentPresenter
x:Name="contentPresenter"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
... />
...
</ControlTemplate>
Create a copy of it with the following change, where selectedTemplate is the key of the DataTemplate you want to cooperate with the ControlTemplate:
<ControlTemplate x:Key="ComboBoxControlTemplateHeader" TargetType="{x:Type ComboBox}">
...
<ContentPresenter
x:Name="contentPresenter"
ContentTemplate="{DynamicResource selectedTemplate}"
... />
...
</ControlTemplate>
Declare the appropriate styles:
<Style
TargetType="{x:Type ComboBox}">
<Setter Property="Template"
Value="{StaticResource ComboBoxControlTemplateBasic}" />
<!-- other generic style setters -->
</Style>
<Style
x:Key="ComboBoxHeader"
x:Name="ComboBoxHeader"
TargetType="{x:Type ComboBox}"
BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="Template"
Value="{StaticResource ComboBoxControlTemplateHeader}" />
<Setter Property="ItemTemplateSelector"
Value="{DynamicResource itemTemplateSelector}"/>
<!-- other specific style setters -->
</Style>
Results
Every ComboBox shares the same look.
The dynamic use of DataTemplate selectedTemplate allows each ListView header gmail-like ComboBox to have the same look with unique binding values.
Take for example the OP ComboBox header plus the following ComboBox with the same item source:
<ComboBox
HorizontalAlignment="Left"
Margin="10,152,0,0"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"/>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
Style="{StaticResource ComboBoxHeader}">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>

WPF: Address nested styles by key

I have a fairly complex WPF UserControl that needs a lot of custom styling, and several different styles for the same control types. The same styles are not used in any other places.
I would like to use nested styles (using Style.Resources) as a sort of namespacing mechanism as follows:
Example user control:
<UserControl Style="{StaticResource AwesomeControl}>
<Grid>
<Button Style="{StaticResource ButtonA}"/>
<Button Style="{StaticResource ButtonB}"/>
</Grid>
</UserControl>
How I want to define my styles:
<ResourceDictionary>
<Style TargetType="UserControl" x:Key="AwesomeControl">
<Style.Resources>
<Style TargetType="Button" x:Key="ButtonA"> </Style>
<Style TargetType="Button" x:Key="ButtonB"> </Style>
</Style.Resources>
</Style>
</ResourceDictionary>
However, this does not work. From what I can tell, it does not seem possible to address nested styles by their key. (I have searched around a lot, but cannot find a single example doing something like this.)
I can make it work easily by removing the nesting of styles, keeping them all at top level. However, then I have to change their keys to something like AwesomeControlButtonA, etc. to distinguish them from other parts of the application
That does not seem ideal to me.
So my question is:
Is something like I am trying with the code above possible? If not, are there other ways of namespacing I can use to prevent awkward keys like AwesomeControlButtonA?
Maybe DynamicResource could solve your problem
<Grid>
<Button Style="{DynamicResource ButtonA}"/>
<Button Style="{DynamicResource ButtonB}"/>
</Grid>
In context:
<Grid>
<Grid.Resources>
<Style x:Key="AW" TargetType="UserControl">
<Style.Resources>
<Style TargetType="Button" x:Key="AB">
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="Button" x:Key="BB">
<Setter Property="Background" Value="Yellow" />
</Style>
</Style.Resources>
</Style>
<Style x:Key="AR" TargetType="UserControl">
<Style.Resources>
<Style TargetType="Button" x:Key="AB">
<Setter Property="Background" Value="Green" />
</Style>
<Style TargetType="Button" x:Key="BB">
<Setter Property="Background" Value="Blue" />
</Style>
</Style.Resources>
</Style>
</Grid.Resources>
<StackPanel>
<UserControl Style="{StaticResource AW}">
<StackPanel>
<Button Content="A" Style="{DynamicResource AB}" />
<Button Content="A" Style="{DynamicResource BB}" />
</StackPanel>
</UserControl>
<UserControl Style="{StaticResource AR}">
<StackPanel>
<Button Content="A" Style="{DynamicResource AB}" />
<Button Content="A" Style="{DynamicResource BB}" />
</StackPanel>
</UserControl>
</StackPanel>
</Grid>

How can I set the background of a StackPanel to an ImageBrush defined in a style resource?

I can apply a background image to a StackPanel with this XAML code:
<StackPanel>
<StackPanel.Background>
<ImageBrush ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
</StackPanel.Background>
...
</StackPanel>
But that's kind of a lot to type when applied to multiple StackPanels. So I'd rather define a Style (aka Static Resource?) that I can quickly apply to the individual StackPanels.
So I started writing this:
<Window.Resources>
<ImageBrush x:Key="SpBg" ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
<Style x:Key="StackPanelBg" TargetType="StackPanel">
<!-- begin invalid xaml -->
<Setter Property="Background" Value="SpBg" />
<!-- end invalid xaml -->
</Style>
</Window.Resources>
So that I'd be able to do this:
<StackPanel Style="{StaticResource StackPanelBg}">
...
</StackPanel>
Except that doesn't work; the Setter line isn't correct. How can I make this work?
Like that:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ImageBrush x:Key="SpBg" ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
<Style x:Key="StackPanelBg" TargetType="StackPanel">
<Setter Property="Background" Value="{StaticResource SpBg}" />
</Style>
</Window.Resources>
<StackPanel Style="{StaticResource StackPanelBg}">
</StackPanel>
</Window>

Rude tab keeps coming to the front

I have a TabControl that uses the following XAML.
<TabControl x:Class="MyApp.Tab.TabContainer"
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:local="clr-namespace:MyApp.Tab"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
ItemsSource="{Binding}">
<TabControl.Resources>
<Style TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
<Setter Property="AcceptsReturn" Value="True"></Setter>
<Setter Property="TextWrapping" Value="WrapWithOverflow"></Setter>
<Setter Property="MaxLines" Value="5000"></Setter>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"></Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"></Setter>
</Style>
<SolidColorBrush x:Key="mouseOverColor" Color="Red"></SolidColorBrush>
<RadialGradientBrush x:Key="glowColor" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5" GradientOrigin="0.5,0.5">
<GradientStop Color="Red" Offset="0.5"></GradientStop>
</RadialGradientBrush>
<RadialGradientBrush x:Key="glowMask" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5" GradientOrigin="0.5,0.5">
<GradientStop Color="#80FFFFFF" Offset="0"></GradientStop>
<GradientStop Color="#80FFFFFF" Offset="0.6"></GradientStop>
<GradientStop Color="#00FFFFFF" Offset="1"></GradientStop>
</RadialGradientBrush>
<DataTemplate x:Key="NewTabHeaderTemplate" DataType="{x:Type local:AddNewTab}">
<DockPanel>
<TextBlock Name="TextBlock" VerticalAlignment="Center" Text="+" FontSize="18" MouseLeftButtonDown="TextBlock_OnMouseLeftButtonDown"></TextBlock>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="MapTabHeaderTemplate" DataType="local:ACTabItemTabItem">
<DockPanel>
<Button Name="btn_TabDelete" DockPanel.Dock="Right" Margin="5,0,0,0" Padding="0" Click="btn_TabDelete_Click" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}">
<Image Source="icon_grey_cross.gif" Height="9" Width="9" Margin="0,0,0,0"></Image>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="bdr_main" Margin="4" BorderThickness="0" >
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Margin="4,4,4,4" ContentSource="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bdr_main" Property="Background" Value="{StaticResource glowColor}"></Setter>
<Setter TargetName="bdr_main" Property="OpacityMask" Value="{StaticResource glowMask}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}"></TextBlock>
</DockPanel>
</DataTemplate>
</TabControl.Resources>
public class AddNewTab : TabItem {}
During the constructor I do this to produce a blank tab with a simple '+' in the header.
_tabItems = new ObservableCollection<ACTabItem>();
try
{
AddNewTab tabAdd = new AddNewTab();
tabAdd.HeaderTemplate = this.FindResource("NewTabHeaderTemplate") as DataTemplate;
_tabItems.Add(tabAdd);
}
this.DataContext = _tabItems;
When the user clicks the '+' I create a new TabItem and add it to the Items collection. I then attempt to bring the new tab to the front. (ImplementTab() simply creates a new TabItem with some values preset by the contents of 'td').
//code up here just collects some data from user to populate 'td'
TabItem newTab = ImplementTab(td);
if (newTab != null)
{
_tabItems.Add((ACTabItem)newTab);
newTab.Focus();
}
If I watch the this_SelectionChanged() event handler I see that the Focus() call does cause a change in SelectedIndex to the index of the newly added tab, but I also see that after the method the new tab code is in completes (right after the Focus()), SelectionChanged is thrown again, but this time with a SelectedIndex of '0' (the original blank tab with the '+' header).
Clicking on a tab throws SelectionChanged only once and I get the expected results.
I am simply trying to have the TabControl focus on a newly added TabItem... how did I mess that up?
I feel that you don't have to inherit your AddNewTab from TabItem if you do databind. It should be just any class, inheriting it from TabItem makes it confusing since TabControl will create a new TabItem to wrap around this data item so all the methods like Focus() on the tab you created will have no effect.
To select the last tab just set the SelectedIndex instead of calling Focus.
if (TabControl1.Items.Count > 0)
TabControl1.SelectedIndex = TabControl1.Items.Count - 1;

WPF trigger for selected items

I am using the MVVM light framework. On one of my pages I have a listbox which has a bound list and a bound selected item. I have a style that should highlight the selected item in that listbox. However, the item is not highlighted until I physically click it (It will not highlight the item when it is just bound).
XAML:
<UserControl.Resources>
<hartvm:ViewLocator x:Key="HartvilleLocator" d:IsDataSource="True" />
<DataTemplate DataType="{x:Type Quotes:QuotePetSummaryItem}">
<Views:QuoteSummaryItem DataContext="{Binding}" />
</DataTemplate>
<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
</Style.Resources>
<Setter Property="BorderBrush" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Opacity" Value="40"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Opacity" Value="100"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource HartvilleLocator}" Path="QuoteSummary" />
</UserControl.DataContext>
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="0">
<TextBlock TextWrapping="Wrap" Text="Quote Summary" Margin="5,0,0,0" FontSize="21.333" Foreground="{DynamicResource ControlHeaderBrush}" FontFamily="Verdana"/>
</Border>
<ScrollViewer d:LayoutOverrides="Height" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1" Margin="10,10,5,10">
<telerik:RadBusyIndicator IsBusy="{Binding IsProcessing}">
<ListBox ItemsSource="{Binding DefaultList}" SelectedItem="{Binding SelectedDefault}" Background="{x:Null}" ItemContainerStyle="{StaticResource ListboxItemStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</telerik:RadBusyIndicator>
</ScrollViewer>
</Grid>
</Border>
</UserControl>
Code (To programmatically select the item in the list box):
public QuotePetSummaryItem SelectedDefault { get; set; }
private void SelectDefault()
{
if (DefaultList== null || DefaultList.First().Pet == null) return;
SelectedDefault = DefaultList.First();
MessengerService.Send(SelectionMessage.Create(SelectedDefault.SubDefault));
}
The message being sent is not important and does some other work on another page. The SelectedDefault property is the only thing that is used for this example.
Someone have an idea as to what I need to do to get this working?
It looks like the binding (and thus your view) doesn't know that the selected item property has changed.
In the setter of SelectedDefault you need to create a notification of some sort using the INotifyPropertyChanged interface.
I just took a quick look at the MVVM light framework and judging by the samples, if your viewmodel inherits from ViewModelBase use a field-backed property and call RaisePropertyChanged:
private QuotePetSummaryItem _selectedDefault;
public QuotePetSummaryItem SelectedDefault
{
get { return _selectedDefault; }
set
{
_selectedDefault = value;
RaisePropertyChanged("SelectedDefault");
}
}
1st you have to set the binding mode for selecteditem to twoway
<ListBox ItemsSource="{Binding DefaultList}" SelectedItem="{Binding SelectedDefault, Mode=TwoWay}" Background="{x:Null}" ItemContainerStyle="{StaticResource ListboxItemStyle}">
2nd in your viewmodel you have to implement INotifyPropertyChanged and raise it properly. look at Rock Counters answer.
if all this not work check your vs output window for binding errors.

Categories

Resources