- 投稿日:2020-10-19T23:52:32+09:00
IAM認証のAWS API GatewayにC#からIAMロールでSigV4署名してアクセスするには
IAM認証を使っているAWSのAPI Gatewayは、APIリクエスト時にSigV4署名が必要です。
前回の記事では、IAMユーザで認証するAPI Gateway呼び出しをC#で書きました。
今回は、EC2インスタンスにアタッチされているIAMロールでの認証です。
前提
IAMロールのアタッチされているEC2インスタンスでC#のコードを実行します。
~/.aws/config
に以下のようにIAMロールが指定されているものとします。[profile default] role_arn = arn:aws:iam::999999999999:role/ROLENAME credential_source = Ec2InstanceMetadataAPI GatewayのリソースポリシーにはこのIAMロールからのAPIアクセスを許可してあるものとします。
動作確認した環境はUbuntu 20.04です。
C#の環境は以下の通り。
$ dotnet --version 3.1.402以下は私の記事でして、このとおりC#をほとんど始めて触っています。C#の流儀と違うところがあったらごめんなさい。
サンプルコードダウンロード
SigV4署名するC#のサンプルコードはAWS公式サイトにありますので、それをダウンロードし、必要なディレクトリのみ残します。
ここの手順の詳細は前回の記事を参照。
$ mkdir sample $ cd sample $ mkdir tmp $ cd tmp $ wget https://docs.aws.amazon.com/AmazonS3/latest/API/samples/AmazonS3SigV4_Samples_CSharp.zip $ unzip AmazonS3SigV4_Samples_CSharp.zip $ cd .. $ mv tmp/AWSSignatureV4-S3-Sample/Signers ./ $ mv tmp/AWSSignatureV4-S3-Sample/Util ./ $ rm -r tmpサンプルソースコードのnamespaceを全置換しておきます。(このコマンドの説明は sedコマンドでディレクトリ内の全ファイルをテキスト全置換するには)
$ grep -rl AWSSignatureV4_S3_Sample Signers | xargs sed -i 's/AWSSignatureV4_S3_Sample/Sample/g' $ grep -rl AWSSignatureV4_S3_Sample Util | xargs sed -i 's/AWSSignatureV4_S3_Sample/Sample/g'C#のプロジェクト作成
dotnet
コマンドでプロジェクトを作成します。$ dotnet new console以下のようなディレクトリ構成になります。
$ tree . ├── obj │ ├── project.assets.json │ ├── project.nuget.cache │ ├── sample.csproj.nuget.dgspec.json │ ├── sample.csproj.nuget.g.props │ └── sample.csproj.nuget.g.targets ├── Program.cs ├── sample.csproj ├── Signers │ ├── AWS4SignerBase.cs │ ├── AWS4SignerForAuthorizationHeader.cs │ ├── AWS4SignerForChunkedUpload.cs │ ├── AWS4SignerForPOST.cs │ └── AWS4SignerForQueryParameterAuth.cs └── Util └── HttpHelpers.cs 3 directories, 13 files
sample.csproj
に以下のようにRootNamespace
の項目を追加します。サンプルダウンロード後に全置換したnamespaceを指定します。<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <RootNamespace>Sample</RootNamespace> </PropertyGroup> </Project>必要なパッケージをダウンロードします。
$ dotnet add package AWSSDK.SecurityTokenC#のソースコード
Program.cs
は以下です。using System; using System.Collections.Generic; using System.Threading.Tasks; using Amazon.Runtime; using Amazon.Runtime.CredentialManagement; using Amazon.SecurityToken; using Amazon.SecurityToken.Model; using Sample.Signers; using Sample.Util; namespace Sample { class Program { private static async Task Run() { // ~/.aws/credentials からRoleArnを読み取る SharedCredentialsFile sharedFile = new SharedCredentialsFile(); sharedFile.TryGetProfile("default", out CredentialProfile credentialProfile); string roleArn = credentialProfile.Options.RoleArn; // IAMロールにassumeする InstanceProfileAWSCredentials instanceCredentials = new InstanceProfileAWSCredentials(); AmazonSecurityTokenServiceClient stsClient = new AmazonSecurityTokenServiceClient(instanceCredentials); AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest { RoleArn = roleArn, RoleSessionName = "test_session", }; var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest); var credentials = assumeRoleResponse.Credentials; var uri = new Uri("https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello"); // 署名するためのソースとなるヘッダ情報 var headers = new Dictionary<string, string> { {AWS4SignerBase.X_Amz_Content_SHA256, AWS4SignerBase.EMPTY_BODY_SHA256}, {"content-type", "text/plain"}, {"x-amz-security-token", credentials.SessionToken}, // IAMロールではこれが必要 }; // 署名を作成 var signer = new AWS4SignerForAuthorizationHeader { EndpointUri = uri, HttpMethod = "GET", Service = "execute-api", Region = "ap-northeast-1" }; var authorization = signer.ComputeSignature(headers, "", // no query parameters AWS4SignerBase.EMPTY_BODY_SHA256, credentials.AccessKeyId, credentials.SecretAccessKey); // リクエストヘッダに署名を追加 headers.Add("Authorization", authorization); // リクエスト実行 // HttpHelpers はUtilで定義 HttpHelpers.InvokeHttpRequest(uri, "GET", headers, null); } static void Main(string[] args) { Run().Wait(); } } }
uri
はAPI GatewayのAPIのURLを入れます。実行
以下のコマンドで実行できます。
$ dotnet runダウンロードしたサンプルコードの
Signers
とUtil
にデバッグ用出力があるので、いろいろ表示されますが、最後にAPI Gatewayからのレスポンスが表示されます。情報源
C#でIAMロールにAssumeする方法がわからず、今回のテーマは難儀でした。わかってしまえば大したことないのですが。
参考にした情報は、前回の記事に加えて、AWS SDK for .NETのAPIレファレンスとPython boto3のソースコードと、参考として
awscurl
というコマンドのソースコードです。AWS SDK for .NETのドキュメントは、説明が少なく、メソッドのシグニチャはわかってもどう使ったらいいのかがわかりませんでした。IAMロールでの署名をしているはずの
awscurl
のソースコードを読み、awscurl
が呼び出しているboto3
のソースコードも読むことで、AWSのAPIをどう呼び出しているのかを把握し、同じことをC#で書くことで実装できました。
- 前回の自分の記事
- AWS SDK for .NETのAPIレファレンス
- Pythonのboto3のソース
awscurl
コマンドのソースboto3はAWSのAPIを呼び出しているだけだと思っていましたが、使いやすいように多くの機能をPythonで実装していることを実感しました。boto3とは違って、AWS SDK for .NETは単にAWS API呼び出しをそのままメソッドにしているだけのように見えます。
- 投稿日:2020-10-19T23:24:27+09:00
【Unity】Randomまとめ
はじめに
ゲーム製作においてRandomを使用する場面は多いと思います。
備忘録としてRandomクラスをまとめてみました。
なお、本記事ではUnityEngine.Random
について記載しています(System.Random
ではない)。Static Properties
insideUnitCircle
半径1の円の内部の点をランダムに返す。
円形上にランダムに敵を出現させたい場合などに使用。
insideUnitSphere
半径1の球体の内部の点をランダムに返す。
球体内部全てなので、浮いてるオブジェクトなどにも使用可能。
onUnitSphere
rotation
rotationUniform
一様な分布でランダムに
Quaternion
を返す。
Random.rotation
では完全なランダムではないみたいです。ただ計算コストはこちらの方が高い。state
乱数生成器の内部状態のすべてを取得、または、設定する。
適当なタイミングでアプリを落としても、再度起動したときに続きからできるようにするために乱数を保存する。value
0.0と 1.0の範囲のランダムな数を返す。
0.0と1.0も含むことに注意。汎用性が高く、Randomクラスのプロパティで基本的に使うのはこれ。Static Methods
ColorHSV
HSVでアルファ値(透明度)をもつランダムな
Color
を返す。
パラメータで色相(hueMin,hueMax)、彩度(saturationMin,saturationMax)、明度(valueMin,valueMax)、アルファ値(透明度:alphaMin,alphaMax)を設定可能。
InitState
シード値を指定し、ランダム数生成器の状態を初期化する。
システム時刻等で決定されるシード値を指定することで、同じ乱数の値を生成することができる。
シード値による擬似乱数については、以下の記事がわかりやすいです。
コンピューターの「ランダム」は本当にランダムなのか?Range
範囲を指定できる、
Random.value
。
intで設定するか、floatで設定するかによって、戻り値の範囲に差がある点に注意。int設定
\text{min}\leqq \text{return} < maxfloat設定
\text{min}\leqq \text{return} \leqq maxまとめ
- Randomクラスは様々な乱数を生成するクラス。
Random.value
とRandom.Range
の使用頻度が圧倒的に高い。Random.rotation
とRandom.rotationUniform
の違いは後日検証したい...
- 投稿日:2020-10-19T15:48:07+09:00
Kafka Trigger のロギングを改善する
自分がメンテをしている Azure Functions Kafka Extensionというライブラリがある。実際に運用してみると、ロギングが不十分であることに気が付いた。
Azure Functions Kafka Extensions
は、 Confluent.Kafka の C#ライブラリを使っている、さらにその内部でネイティブライブラリである Libkafkaが使用されている。通常の実行ログは実行されるが、Libkafkaの方で何か問題が出たとき、例えば
Maximum application poll interval exceeded
が出たあと、Auto-commit をかけようとして失敗しているメッセージが LibKafka から出ているが、ゴリゴリにStandard Output
から出ている。運用もしている側からするとこれはいただけない。しかも、先の Libkafka のライブラリの issue を見ていると、問題が発生したら作者が
Debug
オプションを On にしてとのたまうことが多い。これは、Debug を有効にしたい。条件としてはこの通り。
- Libkafka のデバッグの有効化設定をできるようにしたい
- Libkafka 由来の Standard Output に出ているログをちゃんとしたログに流したい
上記をやってみた。
デバッグの有効化
Libkafka のデバッグの有効化は簡単だ。こちらのとおり、
debug
という設定をしてあげると良い。Consumer
debug = broker,topic,msgProducer
debug = consumer,cgrp,topic,fetch全オプション
all という凶悪なオプションまである。
generic, broker, topic, metadata, feature, queue, msg, protocol, cgrp, security, fetch, interceptor, plugin, consumer, admin, eos, mock, allConfluent.Kafka での実装
Debug の追加
さて、こちらのConfluent.Kafka ではどうするか?
KafkaOptions
というクラスがあり、これが Kafka のhost.json
の項目になる。ここに書けばhost.json
から自動で読んでくれる。Default は空文字ではうまくいかなかったので、null
にした。/// <summary> /// Gets or sets the debug option for librdkafka library. /// Default = "" (disable) /// /// Librdkafka: debug /// </summary> public string LibkafkaDebug { get; set; } = null;こちらを、ConsumerConfig と ProducerConfig に足すだけでよい。これらのクラスのスーパークラスが
ClientConfig
であり、そこに、単純にDebug
に代入するだけでよい。簡単や。これが、Libkafka のライブラリに設定を渡してくれる。KafkaListener L152
ConsumerConfig conf = new ConsumerConfig() { // enable auto-commit EnableAutoCommit = true, // disable auto storing read offsets since we need to store them after calling the trigger function EnableAutoOffsetStore = false, // Interval in which commits stored in memory will be saved AutoCommitIntervalMs = this.options.AutoCommitIntervalMs, // Librdkafka debug options Debug = this.options.LibkafkaDebug,Producer の方は
KafkaProducerFactory
L131 だけど同じようなものだから省略Log のリダイレクト
さて、現在 Standard Output に垂れ流されている libkafka のログどうやって盗んだらええねん、、、と思ってたけど、欲しいの自分だけやないよねということで、あっさりとライブラリにHookが存在した。こんな感じ。
KafkaProducerFactory L76
var builder = new ProducerBuilder<byte[], byte[]>(producerConfig); ILogger logger = this.loggerProvider.CreateLogger("Kafka"); builder.SetLogHandler((_, m) => { logger.LogInformation($"Libkafka: {m?.Message}"); }); return builder.Build();Consumer も似たようなもので、
KafkaListener
L107 だ。省略この
SetLogHandler
で、Action を渡す。
IConsumer と、LogMessage が渡ってくる。IConsumer には様々なメタ情報が入っているが、私が今欲しいのはログのメッセージだけなので、
一旦ここでは、LogMessage
の中身だけ見てみる。ここでは、レベルとかも出てくるが、よくよく考えたらログレベルに合わせてInfomationだけではなく違うものに変えるようにしてもいいかもしれない。一旦ここではInfoにしておく。クエリーできるだけでも様様だ。レビューをお願いしているので、気に食わんかったらアドバイスがもらえるだろう。気になるログの追加
さて、運用していると、ユーザーさんがFunctionをどちらのモードで使っているか?とか知りたいときがある。例えば
Kafka Trigger
は、Function に定義されたパラメータが Array か否かでパラメータがシングルか、複数か決まり実行されるロジックが異なってくる。ただ、頻繁にはログを出したくない。であるので、コンストラクターのところに入れてみたのだが、実際は、Function名をとりたいところ。実際には、executor
オブジェクトがFunction
名を持っているのだが、そのライブラリの作者が実装クラスを internal にしているし、インターフェイスなので、リフレクションで取得するのは危険だろう。今はあきらめたがいい方法があれば教えてほしい。SingleItemFunctionExecutor L22
public SingleItemFunctionExecutor(ITriggeredFunctionExecutor executor, IConsumer<TKey, TValue> consumer, int channelCapacity, int channelFullRetryIntervalInMs, ICommitStrategy<TKey, TValue> commitStrategy, ILogger logger) : base(executor, consumer, channelCapacity, channelFullRetryIntervalInMs, commitStrategy, logger) { logger.LogInformation($"FunctionExecutor Loaded: {nameof(MultipleItemFunctionExecutor<TKey, TValue>)}"); }まとめ
これで一旦当初予定していたロギングの強化が完了した。ついでにライブラリもバージョンアップしておいた。
- 投稿日:2020-10-19T09:15:45+09:00
ReactiveProperty v7.5.0 をリリースしました
最近、ビルド・単体テスト・パッケージング・NuGet への公開・GitHub Releases へのひな型作成まで GitHub Actions で自動化できたのでリリースが楽になりました。リリースノートに追加した機能や変更の一覧を自動で書いてくれるようなのも作りたいけど、どうにかできるんだろうか…
ということで v7.5.0 をリリースしました。
リリースノート
NuGet Gallery | ReactiveProperty今回は 2 つ機能を追加しています。
ObserveProperty, ToReactivePropertyAsSynchronized, FromObject の機能強化
今までは
ObserveProperty
やToReactivePropertyAsSynchronized
でプロパティを指定するときにx => x.Name
のような指定した変数の直接のプロパティしか対象にできませんでした。今回の更新でx => x.Child.Name
のようなネストしたプロパティも指定可能になりました。
これを書いててReactiveProperty.FromObject
だけ、これに対応するのを忘れていたので近いうちに v7.5.1 で対応します orz2020/10/20 にリリースした v7.5.1 で
ReactiveProperty.FromObject
にも対応しました。IFilteredReadOnlyObservableCollection に ObserveElementPropertyChanged などを追加
コレクションの要素のプロパティの変更を監視するための
ObserveElementPropertyChanged
とObserveElementProperty
とObserveElementObservableProperty
をIFilteredReadOnlyObservableCollection<T>
にも対応させました。まとめ
ReactiveProperty.FromObject
は、ネストしたプロパティにまだ対応していないので気を付けてください orzネストしたプロパティへの対応は久しぶりの割とメンドクサイ系の機能追加でしたが、無事実装出来たのでぜひ使ってみてください。問題点等ありましたら GitHub の issues までお願いします。日本語でも OK です。
- 投稿日:2020-10-19T05:47:25+09:00
C#_メソッド
プログラミングを進める上で、何度も似たような処理を書くのは非効率的であり、ソースコードの可読性を下げる要因にもなります。
その為、何度も必要とされる処理は1度だけまとめて書いておくことで、それを複数の箇所から呼び出せるようにすることができます。これを "メソッド" と呼びます。※他の言語では「関数」「サブルーチン」と呼ばれるものです。
メソッド
基本的なメソッドの書き方は次のようになります
Program.cs// [修飾子] 戻り値 メソッド名(型 パラメータ1, 型 パラメータ2, ...) int Add(int x, int y) { // return 戻り値; return x + y; }メソッドは "パラメータ" として値を受け取ることができ、反対に "戻り値" として値を返すことができます。
また、 "return文" で戻り値として定義した型の値を返すことができます。上記Addメソッドはint型の値を2つ受け取り、その和を戻します。
Program.csstatic void Main(string[] args) { // 呼出し方は メソッド名(パラメータ, パラメータ, ...) Console.WriteLine(Add(1, 2)); Console.WriteLine(Add(3, 5)); } static int Add(int x, int y) { return x + y; }出力> 3 > 8エントリポイントもメソッドであり、戻り値はなし(void)かつパラメータとしてstring型配列のargsを受け取っています。
※戻り値の前に付いている "static" は "修飾子" のひとつですが、これは "クラス" の話をするときにまとめて触れます。値渡しと参照渡し
メソッドのパラメータとして値を指定する時、定義上のパラメータを "仮引数" 。メソッドの呼出し側が関数に渡す引数を "実引数" と呼びます。
※ただの用語で、あまり重要ではありません。Program.csstatic void Main(string[] args) { // 3, 5が実引数 Console.WriteLine(Add(3, 5)); } // x, yは仮引数 static int Add(int x, int y) { return x + y; }上記のように単純にパラメータを指定した場合、 "値渡し" と言います。
この時、メソッド内部で仮引数の内容を変更したとしても、当然それは実引数側に反映されることはありません。Program.csstatic void Main(string[] args) { int x = 5; Temp(x); Console.WriteLine(x); } static void Temp(int x) { x = 10; }出力> 5上記に対してパラメータの前にin/out/refを付けることで "参照渡し" を使用することができます。
このin/out/refなどは "パラメータ修飾子" と呼ばれます。Program.csstatic void Main(string[] args) { int x = 0; InMethod(in x); OutMethod(out x); Console.WriteLine(x); RefMethod(ref x); Console.WriteLine(x); } static void InMethod(in int x) { // xへの代入はエラー // x = 1; Console.WriteLine(x); } static void OutMethod(out int x) { // xが未割当てのままメソッドを抜けようとするとエラー // return; x = 2; } static void RefMethod(ref int x) { x = 3; }出力> 0 > 2 > 3それぞれ少しずつ動作が異なるので表にまとめると以下のようになります。
修飾子 呼出し前の初期化 メソッド内での変更・代入 in 必須 不可 out 不要 必須 ref 不要 可能
in修飾子
in修飾子は呼出し側で最初に値を代入し、初期化しておかなければ使用することができません。
またメソッド内部ではin修飾子の付いたパラメータを変更することはできません。
これはメソッドの呼出し側に「値が書き換わらないこと」を保証することになりますが、これは先述の値渡しと同じ動作になります。
値渡しと違い、実引数→仮引数へのデータのコピーが発生しないので、巨大なデータを取り扱いやすいというメリットがあります。out修飾子
out修飾子は呼出し側でのパラメータの初期化を必要としません(初期化しても問題ではありませんが、メソッド内部での代入を強制するので意味がありません)。
メソッド内部ではout修飾子のついたパラメータは何らかの値を代入する必要があり、その値をメソッドの呼出し側へ返却することになります。
つまり、return文による戻り値とは別に値を返したい場合などに使用されます。ref修飾子
ref修飾子はメソッド呼出し側およびメソッド内部のどちらでも初期化や代入を強制することなく、自由に使用することができます。
使い勝手は一番いいですが、反対にメソッド内部と呼出し側でやり取りされるデータの管理が煩雑になりやすいことが挙げられます。上記は値型についての話でしたが、参照型についても同様に値渡しと参照渡しを行うことができます。
代表的な参照型のひとつである配列でその動きを見てみましょう。Program.csstatic void Main(string[] args) { int[] x = new int[] { 1, 2, 3 }; int[] y = new int[] { 4, 5, 6 }; Update(x, ref y); Console.WriteLine(x[0]); Console.WriteLine(y[0]); } static void Update(int[] x, ref int[] y) { x[0] = 10; y[0] = 10; }出力> 10 > 10参照型は値型と違い、持っているデータはメモリ上の実体を指す参照アドレスである為、値渡しでも「アドレスのコピー」を渡すことになり、そのアドレスが指している実体は同じものになります。
なので、参照先の実体に対する変更は、値渡しと参照渡しのどちらでも同じような結果になります。しかし一方で、メソッド内部で新たに参照を割当てた場合、値型と似たような挙動になります。
Program.csstatic void Main(string[] args) { int[] x = new int[] { 1, 2, 3 }; int[] y = new int[] { 4, 5, 6 }; Update(x, ref y); Console.WriteLine(x[0]); Console.WriteLine(y[0]); } static void Update(int[] x, ref int[] y) { x = new int[] { 10, 20, 30 }; y = new int[] { 40, 50, 60 }; }出力> 1 > 40値渡しの時に参照アドレスをコピーしましたが、そこに新たに別の参照先を割当てることで、メソッド内部での仮引数には別の実体2が割当てられました。
しかし実引数の方は変わらず元の実体1を指したままになります。参照渡ししている方は値型と同様に、元の実引数に対して新たに参照先を割当てるため、メソッドの呼び出し側でも値が変更されていることが確認できます。
デフォルト引数
メソッドに渡すパラメータはデフォルトの値を設定しておくことが可能です。
これを "デフォルト引数" と呼びます
Program.csstatic void Main(string[] args) { Output(3); Output(3, 7); } static void Output(int x, int y = 5) { Console.WriteLine(x + y); }出力> 8 > 10デフォルト引数は呼出し側から指定しなかった場合にデフォルトの値となり、指定した場合にはその指定された値となります。
また、デフォルト引数はメソッド定義上、通常のパラメータよりも後ろにのみ設定することが可能です。オーバーロード
基本的に同名のメソッドを複数定義することはできませんが、パラメータが異なれば別のメソッドとして認識されます。
これをメソッドの "オーバーロード" と呼びます。Program.csstatic void Main(string[] args) { Console.WriteLine(Add(2, 3)); Console.WriteLine(Add(2.5, 3.2)); } static int Add(int x, int y) { return x + y; } static double Add(double x, double y) { return x + y; }出力> 5 > 5.7パラメータの型や個数が異なればオーバーロードが可能です。
ただし、戻り値のみ異なる同名のメソッドではオーバーロードとしては認識されません。メソッドについてはここまで。
- 投稿日:2020-10-19T00:01:22+09:00
UWPでメッセージボックスを表示したいとき
UWPでMessageBox.Show()したいとき
各ダイアログの表示確認ようにUWPアプリ作りました。
ソースコードMessageDialog
シンプルなメッセージ表示ダイアログです。
MessageDialogSample.csvar dialog = new MessageDialog("コンテンツ", "タイトル"); _= dialog.ShowAsync();こんな感じでモーダルで表示されます。
アラートなどユーザーに何かを伝えたいときに便利です。ContentDialog
- ボタン1つの場合
ContentDialogSample1.csvar dialog = new ContentDialog() { Title = "OK Dialog Here!!", Content = "Click Ok Button Dialog", CloseButtonText = "Ok" }; var result = await dialog.ShowAsync();
- ボタン2つの場合
ContentDialogSample2.csvar dialog = new ContentDialog() { Title = "Yes No Dialog Here!!", Content = "Click Yes No Button Dialog", PrimaryButtonText = "Yes", CloseButtonText = "No" }; var result = await dialog.ShowAsync();
- ボタン3つの場合
ContentDialogSample3.csvar dialog = new ContentDialog() { Title = "3 Button Dialog Here!!", Content = "Click 3 Button Dialog", PrimaryButtonText = "Allow", SecondaryButtonText = "Delete", CloseButtonText = "Cancel" }; var result = await dialog.ShowAsync();ContentDialogのShowAsync()の戻り値について
namespace Windows.UI.Xaml.Controls { [ContractVersion(typeof(UniversalApiContract), 65536)] [WebHostHidden] public enum ContentDialogResult { None = 0, Primary = 1, Secondary = 2 } }ContentDialogのプロパティに設定した値に対応するボタンが押された際、下記の戻り値を返却します。
プロパティ コマンド 戻り値 CloseButtonText CloseButtonCommand None PrimaryButtonText PrimaryButtonCommand Primary SecondaryButtonText SecondaryButtonCommand Secondary また、それぞれコマンドプロパティも実装されているので、コマンドを作成してプロパティに設定することも可能です。
MessageDialogクラスがsealedクラスであるのに対してContentDialogクラスは継承できるのでレイアウトを拡張したり、好きなコントロールを配置可能なので使いやすいと思います。
応用 InputDialog
- 投稿日:2020-10-19T00:01:22+09:00
UWPでMessageBoxを表示したいとき
各ダイアログの表示確認ようにUWPアプリ作りました。
ソースコードMessageDialog
シンプルなメッセージ表示ダイアログです。
MessageDialogSample.csvar dialog = new MessageDialog("コンテンツ", "タイトル"); _= dialog.ShowAsync();こんな感じでモーダルで表示されます。
アラートなどユーザーに何かを伝えたいときに便利です。ContentDialog
- ボタン1つの場合
ContentDialogSample1.csvar dialog = new ContentDialog() { Title = "OK Dialog Here!!", Content = "Click Ok Button Dialog", CloseButtonText = "Ok" }; var result = await dialog.ShowAsync();
- ボタン2つの場合
ContentDialogSample2.csvar dialog = new ContentDialog() { Title = "Yes No Dialog Here!!", Content = "Click Yes No Button Dialog", PrimaryButtonText = "Yes", CloseButtonText = "No" }; var result = await dialog.ShowAsync();
- ボタン3つの場合
ContentDialogSample3.csvar dialog = new ContentDialog() { Title = "3 Button Dialog Here!!", Content = "Click 3 Button Dialog", PrimaryButtonText = "Allow", SecondaryButtonText = "Delete", CloseButtonText = "Cancel" }; var result = await dialog.ShowAsync();ContentDialogのShowAsync()の戻り値について
namespace Windows.UI.Xaml.Controls { [ContractVersion(typeof(UniversalApiContract), 65536)] [WebHostHidden] public enum ContentDialogResult { None = 0, Primary = 1, Secondary = 2 } }ContentDialogのプロパティに設定した値に対応するボタンが押された際、下記の戻り値を返却します。
プロパティ コマンド 戻り値 CloseButtonText CloseButtonCommand None PrimaryButtonText PrimaryButtonCommand Primary SecondaryButtonText SecondaryButtonCommand Secondary また、それぞれコマンドプロパティも実装されているので、コマンドを作成してプロパティに設定することも可能です。
MessageDialogクラスがsealedクラスであるのに対してContentDialogクラスは継承できるのでレイアウトを拡張したり、好きなコントロールを配置可能なので使いやすいと思います。
応用 InputDialog