当文本框获取焦点时更改容器的背景颜色。

3

我有一个简单的用户控件,其中包含一个TextBox。当TextBox获得焦点时,我想改变用户控件的颜色。以下是我的代码:

<UserControl x:Class="OutLookContactList.ContactSearchControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root" MinHeight="30" Loaded="UserControl_Loaded">

<UserControl.Resources>

    <Style x:Key="searchTextBoxStyle" TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="IsFocused" Value="true">
                <Setter TargetName="root" Property="Background" Value="{StaticResource OnMouseOverColor}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

但是我遇到了“TargetName属性不能在样式Setter上设置”的错误。当文本框获得焦点时,我该如何设置用户控件的背景颜色?

非常感谢!
3个回答

11

将您的UserControl内容包装在一个Border对象中,这样会起作用吗? 如果可以,您可以简单地设置Border的样式,如下所示:

<UserControl x:Class="Sample2.ContactSearchControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="75" Width="300">
    <Border>
        <Border.Style>
            <Style TargetType="Border">
                <Setter Property="Background" Value="White" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsFocused, ElementName=txtSearch}" Value="true">
                        <Setter Property="Background" Value="Black" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Border.Style>
        <StackPanel>
            <TextBox x:Name="txtSearch" Text="Search" />
            <TextBox Text="Other" />
        </StackPanel>
    </Border>
</UserControl>

更新:(回答Sheraz的问题)

我不确定为什么在UserControl内部访问子元素时ElementName无法工作。这可能与可视树构建的方式有关。

至于TriggerDataTrigger的区别:Trigger用于依赖属性,而DataTrigger用于绑定的属性(数据或其他控件)。由于您尝试设置Border的样式,将DataTrigger放置在那里并使其监视TextBox比使TextBox更改Border的外观更有意义。

据我所知,SetterTargetName属性仅适用于DataTemplateControlTemplate中。(此论坛帖子中来自Dr. WPF的信息


是的,它有效。非常感谢Joseph。 有几个问题。 为什么对于UserControl无效,而对于Border有效? 另外,您是如何发现需要使用DataTrigger的?因为我的假设是DataTrigger用于处理数据而不是控件,所以我一直在尝试Trigger(而不是DataTrigger)。 - Sheraz

4

如果您要更改文本框的背景,则需要删除TargetName属性:

<Style x:Key="searchTextBoxStyle" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="IsFocused" Value="true">
            <Setter Property="Background" Value="{StaticResource OnMouseOverColor}" />
        </Trigger>
    </Style.Triggers>
</Style>

并更改想要此样式的文本框:

<TextBox Style="{StaticResource searchTextBoxStyle}" .... />

然而,由于你想改变父用户控件的值,这并不能满足你的要求。

你可以在代码后台添加一个GotFocus事件处理程序,并将改变背景颜色的代码放在其中。


但这不会设置用户控件文本框所在的背景。我想在文本框获得焦点时更改用户控件的颜色。 - Sheraz
在代码中进行更改会增加额外的维护工作,因为我不仅需要在焦点状态下设置颜色,还需要在失去焦点时将颜色恢复正常(工作量增加一倍)。这就是为什么触发器最好,因为它会在 Setter 值不再为 true 时自动重置属性。 - Sheraz

2

以下是一些在Kaxaml中可用的XAML代码:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  
  <Page.Style>
    <Style TargetType="Page">
      <Setter Property="Background" Value="#CCCCD0" />
      <Style.Triggers>
        <DataTrigger Binding="{Binding ElementName=txtSearch, Path=IsFocused}"
                     Value="true">
          <Setter Property="Background" Value="Black" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Page.Style>
  
  <TextBox x:Name="txtSearch" Width="100"
           HorizontalAlignment="Center" VerticalAlignment="Center" />
  
</Page>

您需要使用您的UserControl对象替换Page对象。在VS中编写UserControl之前,我建议您在快速原型工具(如Kaxaml)中测试这些内容,会更容易测试。
请注意,您必须通过属性设置器而不是在Page本身的属性上设置默认颜色(在此示例中为#CCCCD0)。这是因为该属性会覆盖触发器设置的值(因为它是样式触发器),因此即使触发器被触发,也始终会被本地属性规范所取代,这意味着它不会改变。我之所以指出这一点,是因为这是一个相当常见的错误。

这在Kazaml中运行良好,但在IDE中无法工作。奇怪。以下是从输出窗口中得到的异常信息:System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=SearchTextBox'. BindingExpression:Path=IsFocused; DataItem=null; target element is 'ContactSearchControl' (Name='root'); target property is 'NoTarget' (type 'Object)'显然它无法找到SearchTextBox。如果我将xaml复制并粘贴到Kaxaml中,则可以正常工作。似乎与嵌套控件有关,因为我正在另一个用户控件中使用该用户控件。 - Sheraz
Kazaml的链接已经失效,而且会跳转到一个不安全的网站,请勿点击。 - Ciberman
1
@Ciberman 谢谢你让我知道。我已经更新了URL。 - Drew Noakes

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