Eric
Eric

Reputation: 39

Binding StaticResource after changing ItemsSource

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

Answers (1)

thatguy
thatguy

Reputation: 22119

Both TextBoxes 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

Related Questions