Reputation: 39
I'm new with WPF
I've got a simple Style
to set ForeGround
and BackGround
for TextBlock
I'm using a MVVM approach with oViewModel
that exposes two colors.
The text Test Works
and Test Works
works fine.
But the text Test not work
dose not apply the colors. I assume it is because I change the ItemsSource
of inner ListBox
.
Why does the StaticResource
not work in this case.
<Window x:Class="app_manager.FormScripts.FormScriptsJson"
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:local="clr-namespace:app_manager.FormScripts"
xmlns:json="clr-namespace:CtrlJson.Viewer;assembly=CtrlJson"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DataContext="{d:DesignInstance d:Type=local:CViewScriptsJson, IsDesignTimeCreatable=True}"
DataContext="{Binding RelativeSource={RelativeSource self}, Path=oViewModel}"
mc:Ignorable="d"
x:Name="_this"
Title="Scripts Results Analysis" WindowState="Maximized" WindowStyle="ToolWindow">
<Window.Resources>
<Style x:Key="StyleTxt" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{Binding sColorFore}" />
<Setter Property="Background" Value="{Binding sColorBack}" />
</Style>
</Window.Resources>
<DockPanel Background="{Binding sColorBack}">
<TextBlock DockPanel.Dock="Top" Style="{StaticResource StyleTxt}" Text="Test Works"/>
<Grid x:Name="GirdRoot">
<Grid.RowDefinitions>
<RowDefinition MinHeight="450"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition MinHeight="50"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="0" Grid.Column="0" Grid.RowSpan ="3"
Margin="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock DockPanel.Dock="Top" Style="{StaticResource StyleTxt}" Text="Test Works too"/>
<ListBox
Grid.Row="0" Grid.Column="0" Name="LstDataJson" ItemsSource="{Binding oLstDataDay}"
SelectedItem="{Binding Mode=TwoWay, Path=sDataDaySelected}"
IsSynchronizedWithCurrentItem="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding}" Style="{StaticResource StyleTxt}"/>
<TextBlock Text="Test not work" Style="{StaticResource StyleTxt}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</DockPanel>
</Window>
Upvotes: 0
Views: 72
Reputation: 22119
Both TextBox
es for Test Works
and Test Works Too
have their data context set to the view model that contains the sColorFore
and sColorBack
properties. That is why the StyleTxt
can access it. However, the items in your ListBox
have their data context set to the corresponsing data object in the LstDataJson
, which does not contain the sColorFore
and sColorBack
properties, hence they cannot be resolved by the binding.
You can either add those properties to the items, too, or create a second style that uses a RelativeSource
binding to access the data context of their parent ListBox
, which has its data context set to the view model that contains your color properties. Set this style StyleItemTxt
instead of StyleTxt
in your data template.
<Style x:Key="StyleItemTxt" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.sColorFore}"/>
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext.sColorBack}"/>
</Style>
Another option is to remove the color properties completely from the view model and move them to XAML, e.g. in a resource dictionary, so they can be reused in your application. This approach is favorable in general, since it separates view concerns from your business logic and data.
Upvotes: 1