How to change TextBox placeholder text color for a specific element, not global

醉酒当歌 提交于 2019-12-19 06:46:36

问题


MSDN lists the styles and templates for the TextBox class here. I can override these theme resources by creating a ResourceDictionary in App.xaml like this:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Default">
                <SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush" Color="Yellow"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Application.Resources>

but this will affect every TextBox in my app. How can I set this theme for only a specific element?

I've tried putting this dictionary in Page.Resources and even TextBox.Resources for the TextBox that I want to apply it to, but it doesn't work.

I really don't want to have to redefine the Template just to change this property.


EDIT Heena's answer is close, but I would also like to set different colors for light and dark themes because my textbox has a transparent background color.

I managed to achieve this by keeping Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}" as part of the Template (so, in other words, the template is exactly the default as per MSDN) and then specifying in the page resources:

<Page.Resources>
    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Light">
            <SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush" Color="Blue"/>
        </ResourceDictionary>
        ...
    </ResourceDictionary.ThemeDictionaries>
</Page.Resources>

but this now means I have to put a huge ControlTemplate style-setter for the textbox in my page resources too, which is just an exact duplicate of the default anyway!

Does this have something to do with how TextBoxPlaceholderTextThemeBrush is resolved from within the ControlTemplate? i.e. the reason why it discovers my custom theme dictionary is because the ControlTemplate was defined in the same resource dictionary?

How is this supposed to be done? Should I just subclass the textbox so that all that XAML can be moved to another file (even if it is just for one textbox)?


回答1:


Assuming you are using MSDN Textbox Style

Resource Remove Foreground Property from Contencontrol in Template<ContentControl Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"/>

<Page.Resources>
    <!--From MSDN : Default style for Windows.UI.Xaml.Controls.TextBox -->
    <Style x:Key="MsdnTextboxStyle" TargetType="TextBox">          
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                 .....
                 .....
                <ContentControl x:Name="PlaceholderTextContentPresenter"
                              Grid.Row="1"                          
                              Margin="{TemplateBinding BorderThickness}"
                              Padding="{TemplateBinding Padding}"
                              IsTabStop="False"
                              Grid.ColumnSpan="2"
                              Content="{TemplateBinding PlaceholderText}" 
                              IsHitTestVisible="False"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>           
</Page.Resources> 

Xaml

 <StackPanel Orientation="Horizontal">
    <TextBox  PlaceholderText="PlaceholderText here..." Style="{StaticResource MsdnTextboxStyle}" Margin="20"  Foreground="Red" Height="30" Width="120">
        <TextBox.Resources>
            <Style TargetType="ContentControl">
                <Setter Property="Foreground" Value="Green"/>
            </Style>
        </TextBox.Resources>
    </TextBox>
    <TextBox  PlaceholderText="PlaceholderText here..." Style="{StaticResource MsdnTextboxStyle}" Margin="20"  Foreground="Red" Height="30" Width="120">
        <TextBox.Resources>
            <Style TargetType="ContentControl">
                <Setter Property="Foreground" Value="Red"/>
            </Style>
        </TextBox.Resources>
    </TextBox>
    <TextBox  PlaceholderText="PlaceholderText here..." Style="{StaticResource MsdnTextboxStyle}" Margin="20"  Foreground="Red" Height="30" Width="120">
        <TextBox.Resources>
            <Style TargetType="ContentControl">
                <Setter Property="Foreground" Value="Blue"/>
            </Style>
        </TextBox.Resources>
    </TextBox>
</StackPanel>

Update

Resource

Remove Foreground Property from Contencontrol in Template<ContentControl Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"/>

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Default">
                <SolidColorBrush x:Key="ContentControlForeGround" Color="Red"></SolidColorBrush>
                <SolidColorBrush x:Key="ContentControlForeGround1" Color="Yellow"></SolidColorBrush>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Light">
                <SolidColorBrush x:Key="ContentControlForeGround" Color="Blue"></SolidColorBrush>
                <SolidColorBrush x:Key="ContentControlForeGround1" Color="SkyBlue"></SolidColorBrush>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Dark">
                <SolidColorBrush x:Key="ContentControlForeGround" Color="Green"></SolidColorBrush>
                <SolidColorBrush x:Key="ContentControlForeGround1" Color="Chocolate"></SolidColorBrush>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
        <Style x:Key="TextBoxStyle1" TargetType="TextBox">
          .....
           <ContentControl x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2" Content="{TemplateBinding PlaceholderText}"  IsHitTestVisible="False" IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1"/>
           ......                                                       
        </Style>
    </ResourceDictionary>
</Page.Resources>

xaml

<StackPanel Orientation="Horizontal">
    <TextBox  Style="{StaticResource TextBoxStyle1}" PlaceholderText="PlaceholderText here..."  Margin="20"  Foreground="Red" Height="30" Width="170">
        <TextBox.Resources>
            <Style TargetType="ContentControl">
                <Setter Property="Foreground" Value="{StaticResource ContentControlForeGround}"></Setter>
            </Style>
        </TextBox.Resources>
    </TextBox>
    <TextBox  Style="{StaticResource TextBoxStyle1}" PlaceholderText="PlaceholderText here..."  Margin="20"  Foreground="Red" Height="30" Width="170">
        <TextBox.Resources>
            <Style TargetType="ContentControl">
                <Setter Property="Foreground" Value="{StaticResource ContentControlForeGround1}"></Setter>
            </Style>
        </TextBox.Resources>
    </TextBox>
</StackPanel>




回答2:


Old question I know, but I found it incredibly fruststrating that I had to create an entire copy of the TextBox style just to edit the placeholder color of one or two TextBox elements.

So I created this method, which can be used on individual TextBoxes as required:

public static void SetPlaceholderColor(TextBox textBox, Color color)
{
    var textBoxContentGrid = VisualTreeHelper.GetChild(textBox, 0) as Grid;
    for (var i = 0; i < VisualTreeHelper.GetChildrenCount(textBoxContentGrid); i++)
    {
        var visualChild = VisualTreeHelper.GetChild(textBoxContentGrid, i);
        if ((string) visualChild.GetValue(FrameworkElement.NameProperty) != "PlaceholderTextContentPresenter") 
            continue;
        var placeHolderContentControl = visualChild as ContentControl;
        if (placeHolderContentControl != null)
            placeHolderContentControl.Foreground = new SolidColorBrush(color);
    }
}

This should also work for PasswordBoxes, since the TextBox parameter should easily be replacable with just "FrameworkElement"



来源:https://stackoverflow.com/questions/24429522/how-to-change-textbox-placeholder-text-color-for-a-specific-element-not-global

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!