如何更改文本块的背景?

7
这是我XAML结构
<stackpanel>
  <textblock Text="A"></textblock>
  <textblock Text="B"></textblock>
</stackpanel>

Stackpanel可以循环生成更多相同的结构。

当我点击textblock时,如何更改其背景色?

更新:我只想在XAML文件中进行更改,而不使用C#。

默认情况下,我的颜色是黄色,但是当我点击一个textblock时,它的背景将变为蓝色。

更新2:如果我点击A,A会变成蓝色直到我再次点击它。

详细说明:

  1. 我点击A (A是黄色),A将变为蓝色==> A现在是蓝色

  2. 我点击B(B是黄色且A是蓝色),B将变为蓝色,A将变为黄色。

更新3:这个怎么样?

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

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

问题与上述相同。
谢谢!

你需要一个自定义控件。你所需的逻辑不能在控件本身中处理,而是依赖于其他控件,因此纯XAML解决方案是不可能的。 - Dbl
@ Andreas Müller,关于 UPDATE 3 怎么样? - GSP
那又怎样?我的答案对于那种情况仍然适用。 - Dbl
5个回答

4
使用 EventTriggerColor Animation,您可以在 MouseDownMouseLeave 时更改 TextBlock 背景颜色。

XAML 代码

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

更新

使用具有属性IsReadOnly=True的文本框而不是文本块。

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

谢谢@Heena Patil,但是当MouseLeave触发时,颜色会消失。我想要的是:当我点击A(黄色)时,A会变成蓝色,并且一直保持蓝色,直到我点击B。然后B(黄色)将变成蓝色。 - GSP
如果我删除 <EventTrigger RoutedEvent="MouseLeave"> ... </EventTrigger>,那么在单击 TextBlock 后,其背景始终为蓝色。 - GSP

3

编程方式:

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

在XAML中:

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

如果你想在单击文本块时更改背景颜色,应该使用具有触发器的自定义样式。如果你搜索或询问如何使用样式和触发器,这并不难。在XAML设计模式中,你绝对不应该使用C#来实现此目的。


谢谢 @Dmitrij A. 我正在寻找另一个来源。 - GSP
我的VS出了问题,现在无法发布触发器示例。 - Croll

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>

0

这很可能是您问题的解决方案。正如我所指出的,由于您要求一个控件依赖于多种其他控件的特性,仅使用XAML的解决方案是不可能的。

当然,您可以对其余部分进行调整。

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;
            }
        }
    }
}

这不是关于想要什么的问题。而是关于平台如何允许它被设计的。你想要的东西仅使用XAML是不可能实现的。 - Dbl
A有颜色。A没有颜色。 - GSP
@GSP,你也使用了ActiveColor属性吗? - Dbl
抱歉,我昨天已经研究了XAML。那么我该如何处理ActiveColor属性? - GSP
查找“引用自定义控件”。您需要将命名空间引用到类似于Windows、Controls等的命名空间快捷方式中。稍后,您可以使用该快捷方式进行操作,例如<customNamespace:RadioTextbox ActiveColor="Red">yourtext</customNamespace:RadioTextbox>,就这样。 - Dbl
显示剩余4条评论

0

将你的 XAML 结构更改为以下形式

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>

在您的代码后台中使用以下IMultiValueConverter,并添加TextBlockMouseDownEvent事件处理程序以及一个DependencyProperty

////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();
    }
}

如果您想设置默认的 SelectedTextBlock,则只需将要作为默认选定的 TextBlock 名称设置为所选即可。 像这样:
SelectedTextBlockName = "text1";

非常感谢。我还想在XAML文件中进行更改。我找到了适合我的答案:这是**Heena Patil**的帖子。 - GSP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接