次の方法で共有


C#(WPF)のtextboxの背景色と、Disabledの時やReadOnlyの時の背景色の変更について

質問

2020年7月3日金曜日 13:06

いつもお世話になっております。

C#(WPF)のtextboxの背景色と、Disabledの時やReadOnlyの時の背景色の変更についてアドバイスお願い致します。

環境は.Net Framework 4.6 Visual Studio 2017 を使用しております。

textboxの背景色の変更は、Backgroundにて変更が可能ですが、非活性状態(Disabled)の時やReadOnly時の背景色の変更がどうもうまくいきません。

マイクロソフトのサイト(https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/controls/textbox-styles-and-templates)にあるControlTemplateをコピーしてstyleにセットしてみました。

<Style TargetType="{x:Type TextBox}">
  <Setter Property="SnapsToDevicePixels"
          Value="True" />
  <Setter Property="OverridesDefaultStyle"
          Value="True" />
  <Setter Property="KeyboardNavigation.TabNavigation"
          Value="None" />
  <Setter Property="FocusVisualStyle"
          Value="{x:Null}" />
  <Setter Property="MinWidth"
          Value="120" />
  <Setter Property="MinHeight"
          Value="20" />
  <Setter Property="AllowDrop"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TextBoxBase}">
        <Border Name="Border"
                CornerRadius="2"
                Padding="2"
                BorderThickness="1">
          <Border.Background>
            <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
          </Border.Background>
          <Border.BorderBrush>
            <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
          </Border.BorderBrush>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledControlLightColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="ReadOnly">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="MouseOver" />
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ScrollViewer Margin="0"
                        x:Name="PART_ContentHost" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

DisabledControlLightColor あたりを変えればよいかと思い試してみましたが、ダイアログの背景色と同じになってしまい思うような動作になりませんでした。

textboxの非活性状態(Disabled)の時やReadOnly時の背景色の変更方法をご存じの方がいらっしゃいましたらご教授お願い致します。

よろしくお願いいたします。

すべての返信 (4)

2020年7月3日金曜日 14:19 ✅回答済み | 1 票

DisabledControlLightColorの箇所をどのように変更したのでしょうか?

<StackPanel>
    <StackPanel.Resources>
        <Color x:Key="testColor" >#FFFF00FF</Color>

        <Style TargetType="{x:Type TextBox}" x:Key="testStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border Name="Border"
                        CornerRadius="2"
                        Padding="2"
                        BorderThickness="1">
                            <Border.Background>
                                <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
                            </Border.Background>
                            <Border.BorderBrush>
                                <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                            </Border.BorderBrush>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal" />
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                        Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                                                <EasingColorKeyFrame KeyTime="0" Value="Red" />
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="ReadOnly">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                        Storyboard.TargetProperty="(Panel.Background). (SolidColorBrush.Color)">
                                                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource testColor}"/>
                                            </ColorAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="MouseOver" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </StackPanel.Resources>

    <TextBox Text="スタイル未適用" Style="{x:Null}" 
            IsReadOnly="{Binding ElementName=chkIsReadOnly,Path=IsChecked,Mode=OneWay}" 
            IsEnabled="{Binding ElementName=chkIsEnabled,Path=IsChecked,Mode=OneWay}" />

    <TextBox Text="スタイル適用" Style="{StaticResource testStyle}"
            IsReadOnly="{Binding ElementName=chkIsReadOnly,Path=IsChecked,Mode=OneWay}" 
            IsEnabled="{Binding ElementName=chkIsEnabled,Path=IsChecked,Mode=OneWay}" />

    <CheckBox Content="IsReadOnly" x:Name="chkIsReadOnly"/>
    <CheckBox Content="IsEnabled" x:Name="chkIsEnabled" IsChecked="True"/>
</StackPanel>

個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)


2020年7月3日金曜日 15:27

gekkaさん

いつもありがとうございます。

大変助かります。

指定した色には変更できました。ただ、デフォルトの背景色(IsEnabledがtrueの時)が、ダイアログの背景色と同じになってしまい、思うように動かないのです。

gekkaさんのコードでいう、<stackPanel> を <stackPanel Background="Black"> とすると再現すると思います。

私のコードでは<stackPanel>ではなく、Gridでやってましたが、同じでした。 

<Grid Background="Black">

<Text="スタイル適用" Background="Yellow" Style="{StaticResource testStyle}"
            IsReadOnly="{Binding ElementName=chkIsReadOnly,Path=IsChecked,Mode=OneWay}" 
            IsEnabled="{Binding ElementName=chkIsEnabled,Path=IsChecked,Mode=OneWay}" />

いつも本当に助かります。

よろしくお願いいたします。


2020年7月3日金曜日 16:52 | 1 票

提示されているテンプレートだと通常時のバックグランドは

<Border.Background>
    <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
</Border.Background>

になります。
ここでDynamicResourceとなっているので、どこかのリソースでControlLightColorというキーを持ったリソースが定義されている場合はその値を使用して、定義されていなければ値が設定されないという挙動になります。
つまり、リソースが設定されていないと背景色が透明になってしまうという事です。

ですから、

<StackPanel.Resources>
    <Color x:Key="testColor" >#FFFF00FF</Color>
    <Color x:Key="ControlLightColor" >#FFFFFF00</Color>

のようにキーがControlLightColorのリソースを定義してやるか、

<ControlTemplate TargetType="{x:Type TextBoxBase}">
    <Border Name="Border" CornerRadius="2" Padding="2" BorderThickness="1" 
            Background="LemonChiffon">

のように直接バックグランドを指定してやるか、

<ControlTemplate TargetType="{x:Type TextBoxBase}">
    <Border Name="Border" CornerRadius="2" Padding="2" BorderThickness="1" 
            Background="{TemplateBinding Background}">

のようにしてからTextBoxのBackgroundプロパティを参照するようにする方法があります。

<TextBox Text="スタイル適用" Style="{StaticResource testStyle}"
            Background="LightYellow"

個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)


2020年7月6日月曜日 2:41

gekkaさん

詳細な説明ありがとうございます。

まだまだWPF勉強不足で申し訳ございません。

そういうことだったんですね。背景色になってしまう理由、理解できました。

gekkaさんのおかげで、WPFも少しずつ理解できてきました。

もっと勉強しなきゃですね。

ありがとうございました。