2016-06-21 9 views
0

私はCustomControlsというタイトルの新しいWPFプロジェクトで次のことをしました。カスタムWPFテキストボックスコントロールでこのウォーターマークが表示されないのはなぜですか?

ステップ1Controlsフォルダを作成しました。 WatermarkTextBox.csという名前の新しいファイルを追加しました。このC#のコードは、ファイルに追加されました:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 

namespace Controls 
{ 
    public class WatermarkTextBox : TextBox 
    { 
     public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(String), typeof(WatermarkTextBox), new PropertyMetadata(String.Empty)); 

     public String Watermark 
     { 
      get { return (String)GetValue(WatermarkProperty); } 
      set { SetValue(WatermarkProperty, value); } 
     } 
    } 
} 

ステップ2Controlsフォルダ内で、WatermarkTextBox.xaml題した新しいファイルを追加しました。ファイルにこのXAMLを追加しました:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        xmlns:controls="clr-namespace:Controls"> 
    <Style TargetType="{x:Type controls:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> 
     <Style.Resources> 
      <VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None"> 
       <VisualBrush.Visual> 
        <Label Content="{Binding Watermark}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" /> 
       </VisualBrush.Visual> 
      </VisualBrush> 
     </Style.Resources> 
     <Style.Triggers> 
      <Trigger Property="Text" Value="{x:Static sys:String.Empty}"> 
       <Setter Property="Background" Value="{StaticResource WatermarkBrush}" /> 
      </Trigger> 
      <Trigger Property="Text" Value="{x:Null}"> 
       <Setter Property="Background" Value="{StaticResource WatermarkBrush}" /> 
      </Trigger> 
      <Trigger Property="IsKeyboardFocused" Value="True"> 
       <Setter Property="Background" Value="White" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</ResourceDictionary> 

ステップ3Themesフォルダを作成します。 Generic.xamlという名前の新しいファイルを追加します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<ResourceDictionary.MergedDictionaries> 
    <ResourceDictionary Source="/CustomControls;component/Controls/WatermarkTextBox.xaml" /> 
</ResourceDictionary.MergedDictionaries> 

ステップ4MainWindow.xamlで:ファイルにこのXAMLを追加xmlns:controls="clr-namespace:Controls"追加されましたが、新しいWatermarkTextBox定義:

<controls:WatermarkTextBox x:Name="Hostname" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" Watermark="Hello, world."/> 

私はこのカスタムというテキストボックスを参照してくださいコントロールは基づいていますが、私はそれを拡張したウォーターマークを見ません。それはなぜですか、私はどのように透かしを表示できますか? P.S. XAMLの{Binding Watermark}をハードコードされた文字列に変更すると、ウォーターマークが表示されることに注意してください。また、コードをデバッグすると、WatermarkTextBoxが正しい値を取得することがわかります...なぜ、XAMLがそれを表示しないのですか?誰かがこのようなものをどうデバッグすることができますか?

+0

ここで私の答えをチェックしてください。http://stackoverflow.com/questions/37995806/textpreview-for-textbox/37997102#37997102 –

答えて

0

トリックは、既存のWatermarkTextBoxのデフォルトのテンプレートを編集して、コンテンツのスクロールビューだけでなく、家に新しいラベルだけでなく、Gridを導入し、それを拡張するためのVisual Studio用をWindowsアプリケーションと題しブレンドを使用していました透かしすべてでは、私はWatermarkTextBox.xamlにこの変更をしなければならなかった:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:system="clr-namespace:System;assembly=mscorlib" 
       xmlns:controls="clr-namespace:Controls"> 
    <Style TargetType="{x:Type controls:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="controls:WatermarkTextBox"> 
        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
         <Grid> 
          <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> 
          <Label Cursor="IBeam" Visibility="Hidden" x:Name="WatermarkText" Content="{TemplateBinding Watermark}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" /> 
         </Grid> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsEnabled" Value="False"> 
          <Setter Property="Opacity" TargetName="border" Value="0.56"/> 
         </Trigger> 
         <Trigger Property="IsMouseOver" Value="True"> 
          <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/> 
         </Trigger> 
         <Trigger Property="IsKeyboardFocused" Value="True"> 
          <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/> 
         </Trigger> 
         <Trigger Property="Text" Value="{x:Static system:String.Empty}"> 
          <Setter Property="Visibility" Value="Visible" TargetName="WatermarkText" /> 
         </Trigger> 
         <Trigger Property="Text" Value="{x:Null}"> 
          <Setter Property="Visibility" Value="Visible" TargetName="WatermarkText" /> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

編集:あなたは本番でこれをやって考えている場合は、もう一度考えてみて。私は自分自身に考えました。"ああ、このような機能を提供するために必要なすべてのコントロールを拡張するのはとてもいいことです。"残念ながら、PasswordBoxのようないくつかのコントロールクラスは、と封印されているため、これらの状況では問題になります。 ほとんどのハックや拡張機能がそうであるように、実際にはTextBoxと同じ場所にラベルをプログラムで表示したり隠したりする方が簡単です。

+1

元の実装が失敗した主な問題は、リソース内で行われたバインディングがうまくいかないことです。テンプレートに移動すると、ここで行ったように動作します。 – Jai

+0

ええ、その不幸。究極的には、WPFは拡張性に関して混乱ですが、少なくとも技術はシンプルで厳密にフォローされたプログラミングモデルで非常に豊富なユーザーエクスペリエンスを提供することに尽きます。 – Alexandru

関連する問題