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
で塗りつぶしています
結果
塗りつぶせました
あとは閉じた領域だけ塗るようにすればいい感じになりそうなんですが、閉じた領域ってどうやって探すんだろう・・・
WPFのItemsControl.ItemTemplateでリストの一つ前を参照する
WPFのItemsControlはすごく強力だとおもいますよね
ItemsControl.ItemsSourceにリストをバインドして、ItemTemplateで中身を定義すると自由なリストが簡単に作れるので一度使うと癖になります
簡単な例だとこんな感じ
<ItemsControl ItemsSource="{Binding Numbers}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="5"> <TextBlock Text="{Binding}"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
Numbersはランダムな10個の数値リストです
実行結果はランダムな数値が縦に10個並ぶだけなので割愛
普段はこんな感じでお手軽に使えますがごくごくごく偶にアイテムの前の値が欲しい時があります(主にデータ設計に問題がある時ですかねぇ)
そんな時は
{Binding RelativeSource={RelativeSource PreviousData}}
で見ることができるんですね、今日知りました
先ほどのサンプルを更新すると
<ItemsControl Grid.Column="1" ItemsSource="{Binding Numbers}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="5"> <TextBlock Text="{Binding RelativeSource={RelativeSource PreviousData}}"/> <TextBlock Text=" -> "/> <TextBlock Text="{Binding}"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
前の値(リストの一つ上の項目)から今回の値に変わったよ、的な表示をしています
実行結果は
左側は初めに書いたもにで、右が更新後です
こんなことも簡単にできるんですねー
WPFつよい