ディーバ Blog

大阪発 C#の会社、株式会社ディーバの Blog です。

Xamarin.iOS SfDataGrid 編集時のキーボードに完了ボタンを追加する

Syncfusion SfDataGrid で編集する際に キーボードの種類(KeyboardType)を変更 した上で、完了ボタン(Done ボタン)を追加して、編集の確定とキーボードを閉じる方法です。

※ この記事の投稿時点の SfDataGrid のバージョンは v15.2.0.46 です。

f:id:jz5_diva:20170721222320p:plain

Editing 機能で Excel のセルのように編集できます。キーボードの種類を指定するには、カスタム GridCellTextViewRenderer クラスを使います。

さらに、数字のキーパッドの場合、入力を確定する方法・キーボードを閉じる方法がわかりにくいので「完了ボタン」を追加します。このアイデアは「(UITextViewの)キーボードに「閉じる」ボタンを追加する - ながいものには、まかれたくない」から。

public class GridCellTextViewRendererExt : GridCellTextViewRenderer
{
    public override void OnInitializeEditView(DataColumnBase dataColumn, UITextField view)
    {
        base.OnInitializeEditView(dataColumn, view);

        // KeyboardType 変更
        view.KeyboardType = UIKeyboardType.NumberPad;

        // Toolbar 追加
        var toolbar = new UIToolbar(new CGRect(0, 0, 60, 44))
        {
            BarStyle = UIBarStyle.Default,
            Translucent = true
        };
        toolbar.SizeToFit();
        var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
        var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, e) =>
        {
            view.ResignFirstResponder();
        });
        doneButton.Clicked += (o, e) =>
        {
            // 編集を確定する
            dataColumn.Renderer.DataGrid.EndEdit();
        };

        toolbar.Items = new[] { spacer, doneButton };
        view.InputAccessoryView = toolbar;
    }
}

作成したカスタムレンダラーに差し替えます。

_dataGrid = new SfDataGrid(this);

// Add custom renderer    
_dataGrid.CellRenderers.Remove("TextView");
_dataGrid.CellRenderers.Add("TextView", new GridCellTextViewRendererExt());

Xamarin.Android SfDataGrid で編集時にキーボードの種類を変える

Syncfusion SfDataGrid で編集する際にキーボードの種類(InputType)を変更する方法です。

※ この記事の投稿時点の SfDataGrid のバージョンは v15.2.0.46 です。

f:id:jz5_diva:20170722010425j:plain

Editing 機能で Excel のセルのように編集できます。キーボードの種類を指定するには、カスタム GridCellTextViewRenderer クラスを使います。

セルに入力できる値を制限をする場合、Column Types の GridNumericColumn 等も使えます。

public class GridCellTextViewRendererExt : GridCellTextViewRenderer
{
    protected override void OnEnteredEditMode(DataColumnBase dataColumn, View currentRendererElement)
    {
        base.OnEnteredEditMode(dataColumn, currentRendererElement);

        // MappingName により分岐させる場合は次のように参照
        if (dataColumn.GridColumn.MappingName != "ProductNo") return;
        
        // 行のデータにより分岐させる場合は次のように RowData を参照
        // var item = dataColumn.RowData as MyViewModel;

        var editText = currentRendererElement as EditText;
        if (editText == null) return;

        // InputTypes を変更
        editText.InputType = InputTypes.ClassNumber;
    }
}

作成したカスタムレンダラーに差し替えます。

_dataGrid = new SfDataGrid(this);

// Add custom renderer    
_dataGrid.CellRenderers.Remove("TextView");
_dataGrid.CellRenderers.Add("TextView", new GridCellTextViewRendererExt());

Xamarin.iOS SfDataGrid で編集時にキーボードの種類を変える

Syncfusion SfDataGrid で編集する際にキーボードの種類(KeyboardType)を変更する方法です。

※ この記事の投稿時点の SfDataGrid のバージョンは v15.2.0.46 です。

f:id:jz5_diva:20170721215321p:plain

Editing 機能で Excel のセルのように編集できます。キーボードの種類を指定するには、カスタム GridCellTextViewRenderer クラスを使います。

セルに入力できる値を制限をする場合、Column Types の GridNumericColumn 等も使えます。

public class GridCellTextViewRendererExt : GridCellTextViewRenderer
{
    public override void OnInitializeEditView(DataColumnBase dataColumn, UITextField view)
    {
        base.OnInitializeEditView(dataColumn, view);

        // MappingName により分岐させる場合は次のように参照
        if (dataColumn.GridColumn.MappingName != "ProductPrice") return;

        // 行のデータにより分岐させる場合は次のように RowData を参照
        // var item = dataColumn.RowData as MyViewModel;

        // KeyboardType を変更
        var textField = view;
        textField.KeyboardType = UIKeyboardType.NumberPad;
    }
}

作成したカスタムレンダラーに差し替えます。

_dataGrid = new SfDataGrid(this);

// Add custom renderer    
_dataGrid.CellRenderers.Remove("TextView");
_dataGrid.CellRenderers.Add("TextView", new GridCellTextViewRendererExt());

Xamarin.Android SfDataGrid 改行でセルの編集を確定する

Syncfusion SfDataGrid のセル編集をキーボードの改行(Enter/Return キー)で編集を確定する方法です。

※ この記事の投稿時点の SfDataGrid のバージョンは v15.2.0.46 です。

f:id:jz5_diva:20170721211019j:plain

Editing 機能で Excel のセルのように編集できます。改行をハンドリングするには、CurrentCellBeginEdit イベントで処理します。

// _dataGrid: SfDataGrid
_dataGrid.CurrentCellBeginEdit += DataGrid_CurrentCellBeginEdit;
private async void DataGrid_CurrentCellBeginEdit(object sender, GridCurrentCellBeginEditEventArgs args)
{
    await Task.Delay(100);

    if (!(args.Column is GridTextColumn)) return;

    var row = _dataGrid.GetRowGenerator().Items.FirstOrDefault(x => x.RowIndex == args.RowColumnIndex.RowIndex);
    var column = (row.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == "VisibleColumns").GetValue(row) as List<DataColumnBase>).FirstOrDefault(x => x.ColumnIndex == args.RowColumnIndex.ColumnIndex) as IElement;

    if ((column.Element as ViewGroup).ChildCount > 0)
    {
        var editView = (column.Element as ViewGroup).GetChildAt(0) as EditText;
        if (editView != null)
        {
            editView.SetOnEditorActionListener(this);
            editView.SetImeActionLabel("Done", ImeAction.Done);
            editView.SetSingleLine(true);
        }
    }
}

Xamarin.iOS SfDataGrid 改行でセルの編集を確定する

Syncfusion SfDataGrid のセル編集をキーボードの改行(Enter/Return キー)で編集を確定する方法です。

※ この記事の投稿時点の SfDataGrid のバージョンは v15.2.0.46 です。

f:id:jz5_diva:20170721205901p:plain

Editing 機能で Excel のセルのように編集できます。改行をハンドリングするには、CurrentCellBeginEdit イベントで処理します。

// _dataGrid: SfDataGrid
_dataGrid.CurrentCellBeginEdit += DataGrid_CurrentCellBeginEdit;
private async void DataGrid_CurrentCellBeginEdit(object sender, GridCurrentCellBeginEditEventArgs args)
{
    await Task.Delay(100);

    if (!(args.Column is GridTextColumn)) return;

    var row = _dataGrid.GetRowGenerator().Items.FirstOrDefault(x => x.RowIndex == args.RowColumnIndex.RowIndex);
    var column = (row.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == "VisibleColumns").GetValue(row) as List<DataColumnBase>).FirstOrDefault(x => x.ColumnIndex == args.RowColumnIndex.ColumnIndex) as IElement;

    if (column.Element.Subviews.Length > 0)
    {
        if (column.Element.Subviews[0] is UITextField)
        {
            ((UITextField)column.Element.Subviews[0]).ShouldReturn = textField =>
            {
                _dataGrid.EndEdit(); // 編集終了
                return true;
            };
        }
    }
}

5/23 MvvmCross 5.0 がリリース

クロスプラットフォーム MVVM フレームワーク「MvvmCross」がメジャーアップデートして MvvmCross 5.0 がリリースされています。MvvmCross 5.0 は、Xamarin.iOS, Xamarin.Android, Xamarin.Mac, Xamarin.Forms, Universal Windows Platform (UWP), Windows Presentation Framework (WPF) をターゲットとしています(Windows Phone 8.x, Windows 8.x が削除されました)。

f:id:jz5_diva:20170523023535p:plain

少人数で開発されていることもあり 4.x 系のアップデートはもうないと思われます。これから開発する場合 5.x 系を選ばない理由はないでしょう。当ブログも含めて 4.x 系以下の情報は古く 5.0 ではまったく異なる場合があるので最新の情報を確認しましょう。

所感としては、4.x 系と大きく異なっていますが(ようやく便利になった感じ)、そのままアップデートしてもある程度動くと思います。実際 iOS/Android のプロジェクトを先日から 5.0 beta にアップデートする作業をしていました。Navigation(画面遷移と画面間の値の受け渡し)などの作法は全く異なりますが、4.x 系の作法でも動くので少しずつ変更しています。

MvvmCross 5.0

詳しくは、MvvmCross 5.0 release! を参照してください。

以下、気になったところだけピックアップ。

Navigation

もう ShowViewModel は使いません(フレームワーク内部では使っています)。新しい NavigationService を使って、画面遷移します(ViewModel 間でやり取りします)。特に次の2点は大きいですね。

  • ViewModel へ渡すパラメーターが typesafe になりました。
  • ViewModel から戻り値も受け取れるようになりました。

詳しくは、Navigation を参照。

Lifecycle

ViewModel で、View のライフサイクル イベント起点で簡単に処理が記述できるようになっています。ViewModel に次のメソッドが追加されています。

void Appearing();
void Appeared();
void Disappearing();
void Disappeared();

iOS presenter

iOS 用の presenter が改善されています。これまで Modal 表示など View をどのように表示するかを presenter クラスにごりごり記述していましたが、デフォルトである程度使える presenter が実装されています。

例えば、View クラスに MvxModalPresentation 属性を付けるだけで Modal 表示になります。

活用するには、ドキュメントおよびサンプル、そして実装された Presenter のコードも参照する必要があると思います。

ちなみに Android の presenter 改善は MvvmCross 6.0 予定です。

MvvmCross 6.0

既に MvvmCross 6.0 のロードマップも公開されています。

  • Even better Xamarin.Forms support
  • A new default presenter for Android
  • Better handling of Fragments

さらに、.NET Standard 2.0 サポートも含まれています。プラグインの構造の見直しや、より async/await や C# 7 の使用も。

ロードマップの議論は MvvmCross roadmap · Issue #1415 · MvvmCross/MvvmCross でされています。

Xamarin.iOS で psd ファイルを表示

Visual Studio (Xamarin.iOS)の iOS アプリで Photoshop ファイル(.psd ファイル)を、できるだけお手軽に表示する方法です。

UIWebView

iOS 10 から UIWevView で psd ファイルが表示できるようになっています! JPEG 画像と同じように表示するだけで psd ファイルが描画されます。

webView.LoadRequest(new NSUrlRequest("file://***"));

PSD Plugin for Paint.NET

C# によるライブラリでは、Paint.NET で psd ファイルを読み込み・保存可能にするプラグイン「PSD Plugin for Paint.NET」を開発されている方がいます。

Xamarin.iOS プロジェクトに組み込んでみたところ、少しの修正で使えました。コードは割愛。

プラグインのソースコードは、CodePlex にあります(MIT ライセンス)。現在のバージョンは、Version 2.5.0 (Sep 11, 2016)。

特徴は、レイヤー情報も読み込めます。ただし、各レイヤーの合成は Paint.NET 本体の仕事です。合成しようとすると、また別に自力で処理が必要なため、使いどころは難しそうです。。

Magick.NET

最後は参考情報です。

C# 製の画像ライブラリ「Magick.NET」では、psd ファイルも扱えます。ただし Windows 専用です。

.NET Core 版も開発されていますが、現在(Version 7.0.5.502)は、Windows でのみしか動きません。今後、Xamarin.iOS 等と組み合わせて使えるようになるかもしれません。