WPFで雑にウォーターマーク付きのテキストボックスを作る
ウォーターマークのあるテキストボックス(未入力だと透かしがでるやつ)がたまにほしくなりますよね
ガッツリ作る必要もない時はテンプレートで適当に作ってしまえばいいんじゃない?
<Window.Resources> <Style x:Key="WatermarkTextbox" TargetType="{x:Type TextBox}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Grid Background="White"> <ScrollViewer x:Name="PART_ContentHost" Margin="5,0,0,0" VerticalAlignment="Center"/> <TextBlock x:Name="WaterMarkLabel" Text="{TemplateBinding Tag}" Opacity=".5" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0" Visibility="Collapsed"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="Text" Value=""> <Setter Property="Visibility" TargetName="WaterMarkLabel" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid Background="Blue"> <TextBox Style="{StaticResource WatermarkTextbox}" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200" Tag="Input please"/> </Grid>
できあがり
TextBox.TagをTextBlock.Textに入れて、TriggerでTextが空白の時に表示しているだけです
Xamarin.iOSでUITextFieldの変更イベントをとる
CodeBehind(?)でUITextFieldの変更イベントを知りたいとおもいました
ほかのコントロール(UISlider等)と同じようにやればいいとおもっていました
var _text = new UITextField(); _text.ValueChanged += (sender,e)=> { // 変更 };
こんな感じに書いたんですが、これじゃダメだったんですね
_text.AddTarget((sender,e)=>
{
// 変更
},UIControlEvent.EditingChanged);
これなら呼ばれます
理由はNativeなやつにValueChangedが無いからとかなんとかってBugzillaに書いてありました
864 – ValueChanged event is not fired for UITextField
多分忘れたころにまた引っかかると思います
WPFのInkCanvasで塗りつぶす
InkCanvasは線を描くものっぽくて閉じた領域の塗りつぶし、みたいなことは標準ではできなさそうでした
ということでとりあえず適当に塗りつぶすようにしていみます
塗りつぶす人
System.Windows.Ink.Stroke
を継承してDrawCore
で塗りつぶすようにします
ソース
public class CustomInkCanvas : InkCanvas { protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e) { this.Strokes.Remove(e.Stroke); var newStroke = new FillStroke(e.Stroke.StylusPoints, e.Stroke.DrawingAttributes); this.Strokes.Add(newStroke); base.OnStrokeCollected(new InkCanvasStrokeCollectedEventArgs(newStroke)); } } public class FillStroke : Stroke { public FillStroke(StylusPointCollection stylusPoints) : base(stylusPoints) { } public FillStroke(StylusPointCollection stylusPoints, DrawingAttributes drawingAttributes) : base(stylusPoints, drawingAttributes) { } protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes) { if (drawingContext == null) { throw new ArgumentNullException(nameof(drawingContext)); } if (null == drawingAttributes) { throw new ArgumentNullException(nameof(drawingAttributes)); } if (this.StylusPoints.Count < 3) return; var stroke = new Pen(Brushes.Blue, 2); stroke.Freeze(); var fill = new SolidColorBrush(Color.FromArgb(0x80, 0x00, 0xff, 0xff)); fill.Freeze(); var streamGeometry = new StreamGeometry(); using (var geometryContext = streamGeometry.Open()) { geometryContext.BeginFigure(this.StylusPoints[0].ToPoint(), true, false); var points = new PointCollection(); for (var i = 1; i < this.StylusPoints.Count; i++) { points.Add(this.StylusPoints[i].ToPoint()); } geometryContext.PolyLineTo(points, true, false); } drawingContext.DrawGeometry(fill, stroke, streamGeometry); } }
CustomInkCanvas
はStrokeが追加されたときにFillStroke
に置き換える処理をしています
FillStroke.DrawCore
で塗りつぶしています
結果
塗りつぶせました
あとは閉じた領域だけ塗るようにすればいい感じになりそうなんですが、閉じた領域ってどうやって探すんだろう・・・