How to change textblock background?
Asked Answered
R

5

7

This is my xaml structure

<stackpanel>
  <textblock Text="A"></textblock>
  <textblock Text="B"></textblock>
</stackpanel>

Stackpanel, It can loop to generate more same structures.

How can I change background color of texblock when I click it?

UPDATE: I just want change on xaml file not using C#.

Default I has yellow, but when I click a textblock, Its background will change to Blue.

UPDATE 2: If click A, A will change to blue until I click another.

Detail:

  1. I click A(A is yellow), A will change to be blue ==> A is blue

  2. I click B(B is yellow and A is blue), B will change to be blue and A will change to be yellow.

UPDATE 3: How about this?

<stackpanel>
      <textblock Text="A"></textblock>
</stackpanel>

<stackpanel>
      <textblock Text="A"></textblock>
</stackpanel>
<stackpanel>
      <textblock Text="A"></textblock>
</stackpanel>

The question is same above

Thanks!

Reichenberg answered 6/1, 2015 at 4:15 Comment(3)
you'll need a custom control for that. the logic you need can not be dealt within the control itself but depends on other controls, thus a pure xaml solution is impossibleKyongkyoto
@ Andreas Müller How about UPDATE 3?Reichenberg
what about it? my answer should still work for that case too.Kyongkyoto
E
5

Using EventTrigger and Color Animation you can change color of TextBlock Background color on MouseDown or MouseLeave


xaml code

 <StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Style.Triggers>
                <EventTrigger RoutedEvent="MouseDown">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Yellow" To="Blue" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Blue" To="Yellow" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <TextBlock Text="A" Background="Yellow"></TextBlock>
    <TextBlock Text="B" Background="Yellow"></TextBlock>
</StackPanel>

Update

Use TextBox with property IsReadOnly=True instead of textblock.

    <StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBox"> 
            <Setter Property="Background" Value="Yellow"></Setter>
            <Setter Property="BorderThickness" Value="0"></Setter> 
            <Setter Property="IsReadOnly" Value="True"></Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="TextBox.GotFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Yellow" To="Blue" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="TextBox.LostFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Blue" To="Yellow" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <TextBox Text="A"></TextBox>
    <TextBox Text="A"></TextBox>
</StackPanel>
Eternize answered 6/1, 2015 at 5:36 Comment(2)
Thanks @Eternize Patil, But when MouseLeave raise the color disappear. I want: When I click A (Yellow), A has changed to be blue and It will be blue until I click on B. Then B (yellow) will changed to be blue.Reichenberg
If I remove <EventTrigger RoutedEvent="MouseLeave"> ... </EventTrigger>, TextBlock's background always has blue after click it.Reichenberg
C
5

Programmatically:

textBlock1.Background = new SolidColorBrush(Colors.Yellow);

In XAML:

<TextBlock Name="textBlock1">
    <TextBlock.Background>
        <SolidColorBrush Color="Yellow" />
    </TextBlock.Background>
</TextBlock>

To change background color when you click on a textBlock, you should use custom style with triggers. This is not hard, if you will search or ask about using styles and triggers. You definetely should not use C# for this in XAML design patterns.

Covell answered 6/1, 2015 at 4:24 Comment(2)
Thanks @Dmitrij A. I am searching another source.Reichenberg
my VS broken so i can't post triggers sample now.Covell
E
5

Using EventTrigger and Color Animation you can change color of TextBlock Background color on MouseDown or MouseLeave


xaml code

 <StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Style.Triggers>
                <EventTrigger RoutedEvent="MouseDown">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Yellow" To="Blue" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Blue" To="Yellow" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <TextBlock Text="A" Background="Yellow"></TextBlock>
    <TextBlock Text="B" Background="Yellow"></TextBlock>
</StackPanel>

Update

Use TextBox with property IsReadOnly=True instead of textblock.

    <StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBox"> 
            <Setter Property="Background" Value="Yellow"></Setter>
            <Setter Property="BorderThickness" Value="0"></Setter> 
            <Setter Property="IsReadOnly" Value="True"></Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="TextBox.GotFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Yellow" To="Blue" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="TextBox.LostFocus">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Blue" To="Yellow" Duration="0:0:0.1"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <TextBox Text="A"></TextBox>
    <TextBox Text="A"></TextBox>
</StackPanel>
Eternize answered 6/1, 2015 at 5:36 Comment(2)
Thanks @Eternize Patil, But when MouseLeave raise the color disappear. I want: When I click A (Yellow), A has changed to be blue and It will be blue until I click on B. Then B (yellow) will changed to be blue.Reichenberg
If I remove <EventTrigger RoutedEvent="MouseLeave"> ... </EventTrigger>, TextBlock's background always has blue after click it.Reichenberg
T
0
  <TextBlock Text="Hello, styled world!" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Setter Property="Background" Value="Yellow"></Setter>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" Value="Blue" />
                                <Setter Property="TextDecorations" Value="Underline" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
Titre answered 6/1, 2015 at 6:7 Comment(0)
K
0

This willbe the solution for your problem most likely. As i pointed out a xaml only solution won't be possible due to the nature of your requirement that you want one control to be dependent on a varierty of other controls.

You can fiddle around with the rest of it of course.

public class RadioTextblock : TextBlock
{
    static RadioTextblock()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(RadioTextblock), new FrameworkPropertyMetadata(typeof(RadioTextblock)));
    }

    public static readonly DependencyProperty GroupProperty = DependencyProperty.Register(
        "Group", typeof (string), typeof (RadioTextblock), new PropertyMetadata(string.Empty));

    public string Group
    {
        get { return (string) GetValue(GroupProperty); }
        set { SetValue(GroupProperty, value); }
    }

    public static readonly DependencyProperty ActiveColorProperty = DependencyProperty.Register(
        "ActiveColor", typeof (Brush), typeof (RadioTextblock), new PropertyMetadata(default(Brush)));

    public Brush ActiveColor
    {
        get { return (Brush) GetValue(ActiveColorProperty); }
        set { SetValue(ActiveColorProperty, value); }
    }

    public static readonly DependencyProperty RestorationColorProperty = DependencyProperty.Register(
        "RestorationColor", typeof (Brush), typeof (RadioTextblock), new PropertyMetadata(default(Brush)));

    public Brush RestorationColor
    {
        get { return (Brush) GetValue(RestorationColorProperty); }
        set { SetValue(RestorationColorProperty, value); }
    }

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        // there may be a better hook for this. but i'm not writing custom controls that often. anything after styles are applied should be good
        RestorationColor = Background;
    }

    protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
    {
        RestoreOtherBackgrounds(this);
        base.OnPreviewMouseDown(e);
    }

    private void RestoreOtherBackgrounds(RadioTextblock radioTextblock)
    {
        var topParent = GetTopMostParent(radioTextblock);
        var controlsWithGroup = GetChildrenRecursive<RadioTextblock>(topParent).ToLookup(d => (string)d.GetValue(GroupProperty));
        var similar = controlsWithGroup[radioTextblock.Group];
        foreach (var match in similar)
        {
            if (match == radioTextblock)
            {
                match.Background = ActiveColor;
            }
            else
            {
                match.Background = match.RestorationColor;
            }
        }
    }

    private DependencyObject GetTopMostParent(RadioTextblock radioTextblock)
    {
        DependencyObject current = radioTextblock;
        while (current != null)
        {
            var cParent = VisualTreeHelper.GetParent(current);
            if (cParent == null || cParent == current)
                break;

            current = cParent;
        }

        return current;
    }

    private IEnumerable<T> GetChildrenRecursive<T>(DependencyObject current) where T : DependencyObject
    {
        T casted;
        var childCount = VisualTreeHelper.GetChildrenCount(current);
        for (int i = 0; i < childCount; i++)
        {
            var currentChild = VisualTreeHelper.GetChild(current, i);
            casted = currentChild as T;
            if(casted != null)
                yield return casted;

            foreach (var subChild in GetChildrenRecursive<T>(currentChild))
            {
                if (subChild != null)
                    yield return casted;
            }
        }
    }
}
Kyongkyoto answered 6/1, 2015 at 7:4 Comment(9)
Thanks @Andreas Müller, But I just want to change on xaml file.Reichenberg
this isn't about wanting something. it's about how the platform allows it to be designed. what you want is impossible using just xamlKyongkyoto
stackpanel is under treeview. So I can change background item of treeview then stackpanel has changed (stackpanel is an item). But AAA is item background, AAA is stackpanel background (I want this view).Reichenberg
A has color. A has not colorReichenberg
@Reichenberg did you use the ActiveColor Property too?Kyongkyoto
Sorry, I has researched xaml yesterday. So how can i do with ActiveColor Property ?Reichenberg
@Reichenberg Well that explains it :) You just exchange your textblock with a RadioTextblock and then you set the property in Xaml as usual with the color you want to be used upon a clickKyongkyoto
RadioTextblock: The type RadioTextblock was not foundReichenberg
look up "referencing custom controls". you'll have to reference a namespace to a namespace shortcut like it's usually in windows, controls etc. later on you use that shortcut to do it like <customNamespace:RadioTextbox ActiveColor="Red">yourtext</customNamespace:RadioTextbox> and that's itKyongkyoto
T
0

Change your XAML structure as follow's

xmlns:local="clr-namespace:your_assembly_Name"
.....  
<StackPanel>
    <StackPanel.Resources>
        <local:BackgroundConverter x:Key="backgroundConverter"/>
        <Style TargetType="TextBlock">
            <EventSetter Event="MouseDown" Handler="TextBlockMouseDownEvent" />
            <Setter Property="Background">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource backgroundConverter}">
                        <Binding Path="Name" RelativeSource="{RelativeSource Self}"/>
                        <Binding Path="SelectedTextBlockName"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </StackPanel.Resources>
    <TextBlock x:Name="text1" Text="Header"/>
    <TextBlock x:Name="text2" Text="Header"/>
    <TextBlock x:Name="text3" Text="Header"/>
    <TextBlock x:Name="text4" Text="Header"/>
</StackPanel>

Use following IMultiValueConverter and Add TextBlockMouseDownEvent Event Handler as well as One DependencyProperty in your code behind.

////DependencyProperty
public string SelectedTextBlockName
{
    get { return (string)GetValue(SelectedTextBlockNameProperty); }
    set { SetValue(SelectedTextBlockNameProperty, value); }
}

// Using a DependencyProperty as the backing store for SelectedTextBlock.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedTextBlockNameProperty =
    DependencyProperty.Register("SelectedTextBlockName", typeof(string), typeof(Class_Name), new PropertyMetadata(null));

.......

private void TextBlockMouseDownEvent(object sender, MouseButtonEventArgs e)
{
    TextBlock txtBlock = sender as TextBlock;
    if (txtBlock != null)
    {
        SelectedTextBlockName = txtBlock.Name;
    }
}

.......

public class BackgroundConverter : IMultiValueConverter
{
    /// <summary>
    /// Values[0] = Name of TextBlock
    /// values[1] = SelectedTextBlockName
    /// If matches then it is selected
    /// </summary>
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values[0] != null && values[1] != null && values[0].ToString() == values[1].ToString())
            return new SolidColorBrush(Colors.Blue);
        return new SolidColorBrush(Colors.White);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

If you want to set default SelectedTextBlock then just set the TextBlock name which you want as a default to be selected. like this :

SelectedTextBlockName = "text1";
Tonnie answered 6/1, 2015 at 12:34 Comment(1)
Thank you so much. I also want to change in xaml file. And I found the answer for me: This is post of **Heena Patil**Reichenberg

© 2022 - 2024 — McMap. All rights reserved.