20200421のC#に関する記事は13件です。

View を支えるトリガーアクション

はじめに

オレオレ解釈の覚え書き その5

トリガーアクションについてです。
※今回も Expression Blend に付属する Trigger, Action について触れていきます。

本文

トリガーは動作のきっかけを通知する機構で、トリガーが何かを感知したときに行われる処理がアクションです。これらはセットで使用されるため、まとめてトリガーアクションと呼ばれています。
トリガーにはいくつか種類があります。ここではコントロールのイベント発生を感知する EventTrigger を使ってみます。以下の例では、メッセージボックスを表示するアクションを用意し、ウィンドウがロードされたときに起動するように紐づけています。

TriggerAction
namespace TestApp.Views.Behaviors
{
    public class MessageAction : TriggerAction<DependencyObject>
    {
        protected override void Invoke(object parameter)
        {
            var owner = this.AssociatedObject as Window ?? Window.GetWindow(this.AssociatedObject);
            MessageBox.Show(owner, "メッセージ", "タイトル", MessageBoxButton.OK, MessageBoxImage.Information);
        }
    }
}
View
<Window x:Class="TestApp.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:behaviors="clr-namespace:TestApp.Views.Behaviors">

    <!-- トリガーとアクションを設定できる -->
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <behaviors:MessageAction/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Window>

この例のような動作はビヘイビアでも実現できるでしょう。両者の違いは、同じ処理をさせるか、同じふるまいをさせるかにあります。アクションは処理だけが切り出されており、特定のイベントに依存しません。イベントの感知はトリガーに任せています。一方でビヘイビアは処理のきっかけとなるイベントまで丸ごと部品化されています。

おわりに

今回はトリガーアクションについてでした。
数回に分けてまとめてきた View を支える要素ですが、少し掘り下げただけでも、この構成の奥深さが垣間見えてきます。これらの仕組みを活用することで、処理どうしの癒着が減り、再利用しやすいプログラムの構築に近づくはずです。

View は一区切りにして、次回は ViewModel の相互作用処理についてまとめてみます。今回のテーマであるトリガーアクションにも関係がある仕組みになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更ながらWPFに置き換えてみる(14)

クリック透過ON/OFFの機能追加

アイコンモードで表示する際、秒とかアナログ時計とかののイメージだけをWindow化して画面に出します。そもそも地味機能ツールなんで、透過させて目立たない表示にできるという意図なんですが、どうせなら設定でクリックイベントを透過させてみようということで方法を検索するとQiita内のページにありがたい記述がありました「→WPF で オーバーレイ表示をする
クリック透過にすると当然対象Window上のコントロール操作ができなくなるので、そこはNotifyIcon上のコンテキストメニューでON/OFF可能にしてみました。

無題.png

また同じメニュー内でWindowのTOPMOSTも同様に切り替えできる設定なので、クリック透過のON/OFFの判定時にはその分の計算をやってます。

    public class G
    {
        //・・・略
        public static int catch_extendStyle;    //拡張WINDOW イベント受け
        public static int through_extendStyle;  //      イベント透過
    }
//・・・中略・・・
        //Icon mode Ignore click event
        protected const int GWL_EXSTYLE = (-20);
        protected const int WS_EX_TRANSPARENT   = 0x00000020;
        protected const int WS_EX_TOPMOST       = 0x00000008;

//・・・中略・・・
        protected override void OnSourceInitialized(EventArgs e)
        {
            //Icon Mode時のクリックEventの受け・スルー切り替え

            base.OnSourceInitialized(e);

            //WindowHandle(Win32) を取得
            var handle = new WindowInteropHelper(this).Handle;
            //クリックをキャッチ
            int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
            G.catch_extendStyle = extendStyle;
            //クリックをスルー
            extendStyle |= WS_EX_TRANSPARENT; //フラグの追加
            G.through_extendStyle = extendStyle;
            //初期はキャッチで設定
            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);

        }
//・・・中略・・・
        private void NotifyIcon_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            //ノティファイアイコン上でのコンテキストメニュー全般の処理
            MenuItem selectedItem = (MenuItem)sender;
            switch (selectedItem.Tag.ToString())
            {
                case "0":   //show/hide
                   //・・・中略・・・
                case "8":   //Icon Mode click ignore on/off
                    if (G.MODE == 2)    //ICONモードの場合のみ許可
                    {
                        var handle = new WindowInteropHelper(this).Handle;
                        int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
                        if (this.Topmost == false)
                        {
                            extendStyle ^= WS_EX_TOPMOST;  //TopMostの場合はその分の値を減算
                        }
                        if (extendStyle == G.catch_extendStyle)
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.through_extendStyle);
                            this.IgnoreEvent.IsChecked = true;
                        }
                        else
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);
                            this.IgnoreEvent.IsChecked = false;
                        }
                    }
                    else this.IgnoreEvent.IsChecked = false;
                    break;
                  //・・・中略・・・
            }
        }

こんな感じになります。
(クリック受け→クリック無視→TOPMOST→クリック受けで変化させています)

listview_itemdelete5.gif

時報お知らせ表示

こんな感じの体裁で実装。
listview_itemdelete6.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更ながらWPFに置き換えてみる(13)

クリック透過ON/OFFの機能追加

アイコンモードで表示する際、秒とかアナログ時計とかののイメージだけをWindow化して画面に出します。そもそも地味機能ツールなんで、透過させて目立たない表示にできるという意図なんですが、どうせなら設定でクリックイベントを透過させてみようということで方法を検索するとQiita内のページにありがたい記述がありました「→WPF で オーバーレイ表示をする
クリック透過にすると当然対象Window上のコントロール操作ができなくなるので、そこはNotifyIcon上のコンテキストメニューでON/OFF可能にしてみました。

無題.png

また同じメニュー内でWindowのTOPMOSTも同様に切り替えできる設定なので、クリック透過のON/OFFの判定時にはその分の計算をやってます。

    public class G
    {
        //・・・略
        public static int catch_extendStyle;    //拡張WINDOW イベント受け
        public static int through_extendStyle;  //      イベント透過
    }
//・・・中略・・・
        //Icon mode Ignore click event
        protected const int GWL_EXSTYLE = (-20);
        protected const int WS_EX_TRANSPARENT   = 0x00000020;
        protected const int WS_EX_TOPMOST       = 0x00000008;

//・・・中略・・・
        protected override void OnSourceInitialized(EventArgs e)
        {
            //Icon Mode時のクリックEventの受け・スルー切り替え

            base.OnSourceInitialized(e);

            //WindowHandle(Win32) を取得
            var handle = new WindowInteropHelper(this).Handle;
            //クリックをキャッチ
            int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
            G.catch_extendStyle = extendStyle;
            //クリックをスルー
            extendStyle |= WS_EX_TRANSPARENT; //フラグの追加
            G.through_extendStyle = extendStyle;
            //初期はキャッチで設定
            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);

        }
//・・・中略・・・
        private void NotifyIcon_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            //ノティファイアイコン上でのコンテキストメニュー全般の処理
            MenuItem selectedItem = (MenuItem)sender;
            switch (selectedItem.Tag.ToString())
            {
                case "0":   //show/hide
                   //・・・中略・・・
                case "8":   //Icon Mode click ignore on/off
                    if (G.MODE == 2)    //ICONモードの場合のみ許可
                    {
                        var handle = new WindowInteropHelper(this).Handle;
                        int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
                        if (this.Topmost == false)
                        {
                            extendStyle ^= WS_EX_TOPMOST;  //TopMostの場合はその分の値を減算
                        }
                        if (extendStyle == G.catch_extendStyle)
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.through_extendStyle);
                            this.IgnoreEvent.IsChecked = true;
                        }
                        else
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);
                            this.IgnoreEvent.IsChecked = false;
                        }
                    }
                    else this.IgnoreEvent.IsChecked = false;
                    break;
                  //・・・中略・・・
            }
        }

こんな感じになります。
(クリック受け→クリック無視→TOPMOST→クリック受けで変化させています)

listview_itemdelete5.gif

時報お知らせ表示

こんな感じの体裁で実装。
listview_itemdelete6.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更ながらWPFに置き換えてみる(13)

クリック透過ON/OFFの機能追加

アイコンモードで表示する際、秒とかアナログ時計とかののイメージだけをWindow化して画面に出します。アプリにはWindow透過設定を持ってます(Window Opacity利用)。そもそも地味機能ツールなんで、透過させて目立たない表示にできるという意図なんですが、どうせなら設定でクリックイベントを透過させたほうがいいんではと思い、んで方法を検索するとQiita内のページにありがたい記述がありました「→WPF で オーバーレイ表示をする
クリック透過にすると当然対象Window上のコントロール操作ができなくなるので、NotifyIcon上のコンテキストメニューでON/OFF切り替え可能に。

無題.png

メインウインドウひらっきっぱなし→ずっとWinハンドラ値は変わらないので、最初にグローバルにクリック受けと無視のそれぞれの値を保存しておきます。
WindowのTOPMOSTも変更可能にしてるので、コンテキストメニューでのクリック透過のON/OFFの判定時にはTOPMOST値も考慮してスイッチしてます。

    public class G
    {
        //・・・略
        public static int catch_extendStyle;    //拡張WINDOW イベント受け用の保存変数
        public static int through_extendStyle;  //      イベント透過用の保存変数
    }

//・・・中略・・・
        //Icon mode Ignore click event
        protected const int GWL_EXSTYLE = (-20);
        protected const int WS_EX_TRANSPARENT   = 0x00000020; //透過時の値
        protected const int WS_EX_TOPMOST       = 0x00000008; //topmost時の値
        [DllImport("user32")]
        protected static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32")]
        protected static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwLong);
//・・・中略・・・
        protected override void OnSourceInitialized(EventArgs e)
        {
            //Icon Mode時のクリックEventの受け・スルー切り替え

            base.OnSourceInitialized(e);

            //WindowHandle(Win32) を取得
            var handle = new WindowInteropHelper(this).Handle;
            //クリックをキャッチする場合の値を算出して保存
            int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
            G.catch_extendStyle = extendStyle;
            //クリックをスルーする場合の値を算出して保存
            extendStyle |= WS_EX_TRANSPARENT; //フラグの追加
            G.through_extendStyle = extendStyle;
            //初期はキャッチで設定
            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);

        }
//・・・中略・・・
        private void NotifyIcon_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            //ノティファイアイコン上でのコンテキストメニュー全般の処理
            MenuItem selectedItem = (MenuItem)sender;
            switch (selectedItem.Tag.ToString())
            {
                case "0":   //show/hide
                   //・・・中略・・・
                case "8":   //Icon Mode click ignore on/off
                    if (G.MODE == 2)    //ICONモードの場合のみ許可
                    {
                        var handle = new WindowInteropHelper(this).Handle;
                        int extendStyle = GetWindowLong(handle, GWL_EXSTYLE);
                        if (this.Topmost == false)
                        {
                            extendStyle ^= WS_EX_TOPMOST;  //TopMostでない場合はその分の値を減算
                        }
                        if (extendStyle == G.catch_extendStyle)
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.through_extendStyle);
                            this.IgnoreEvent.IsChecked = true;
                        }
                        else
                        {
                            SetWindowLong(handle, GWL_EXSTYLE, G.catch_extendStyle);
                            this.IgnoreEvent.IsChecked = false;
                        }
                    }
                    else this.IgnoreEvent.IsChecked = false;
                    break;
                  //・・・中略・・・
            }
        }

こんな感じになります。
(クリック受け→クリック無視→TOPMOST→クリック受けで変化させています)

listview_itemdelete5.gif

時報お知らせ表示

こんな感じの体裁で実装。
listview_itemdelete6.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[C#] プロパティを文字列で指定して値をsetし、forループ中で使用する

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

あるクラスで、同じようなデータを複数個、プロパティとして持っているものがあった。そいつが、

public List<double> DataCollection = List<double>();

と持てばいいのに、

public double Data1 = 0.0;
public double Data2 = 0.0;



public double Data20 = 0.0;

みたいな形で持っていたために、そこに値を入れるときにいちいちData1 = 10.0;を20回書かないといけない、みたいなことになりものすごく冗長となった。

元のプロパティを色々な事情で直せない場合でも、せめてforでくるくる回して、値を全部のプロパティに代入できるようにしたい。

今回の解

System.Reflection.PropertyInfoクラスのメソッドを使用した。

やりたいことができた.cs
class Program
{

    static void Main(string[] args)
    {
        var MyData = new MyData();

        for (int i = 0; i < 3; i++)
        {
            MyData.GetType().GetProperty("Data" + (i + 1)).SetValue(MyData, i);
        }

        Console.WriteLine($"OriginalProperty : {MyData.Data1}, {MyData.Data2}, {MyData.Data3}");
    }
}

public class MyData
{
    public double Data1 { get; set; } = 0.0;
    public double Data2 { get; set; } = 0.0;
    public double Data3 { get; set; } = 0.0;
}

実行結果
image.png

GetProperty
image.png

SetValue
image.png

失敗例

C言語のポインタの配列のイメージで、下記のようにしたが、うまくいかなかった。
(暫くC言語書いてない&想像で書いて実際にコンパイルしてないので正しく動くか不明)

C言語のイメージ、こういうことがC#でしたい.c
double data1 = 0;
double data2 = 0;
double data3 = 0;

double* DataCollection[3] = { &data1, &data2, &data3 };

void main()
{
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        *DataCollection[i] = 10;
    }
}

そのイメージで書いた.cs
class Program
{

    static void Main(string[] args)
    {
        var MyData = new MyData();
        double[] DataCollection = { MyData.Data1, MyData.Data2, MyData.Data3 };
        for (int i = 0; i < 3; i++)
        {
            DataCollection[i] = i;
        }
        Console.WriteLine($"Array            : {DataCollection[0]}, {DataCollection[1]}, {DataCollection[2]}");
        Console.WriteLine($"OriginalProperty : {MyData.Data1}, {MyData.Data2}, {MyData.Data3}");
    }
}

class MyData
{
    public double Data1 = 0.0;
    public double Data2 = 0.0;
    public double Data3 = 0.0;
}

実行結果
image.png
元のプロパティの値を一気にforで変えたいのに、変わってない。

しらべたいこと

今回は、Data1Data2みたいに末尾に連続した数字がついていたので今回のやり方でループで処理できたが、そうでない場合でもループさせたいときは、やっぱりC言語の時みたいに書きたい。
なんかやり方ないか??

参考

https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.propertyinfo?view=netframework-4.8

[C#] 文字列でプロパティ名を指定してアクセス(参照・更新)する方法
https://webbibouroku.com/Blog/Article/access-property

【C#】プロパティ名でプロパティにアクセスする
https://qiita.com/tokishirazu/items/66a25331d4c78980366e

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ASP.NET Core アプリの Cookie に secure フラグを立てる

ASP.NET Core アプリの Cookie に secure フラグを立てる

セキュリティ監査とかで secure フラグを立てないといけない人向け.

Startup.cs を開き、先頭に using Microsoft.AspNetCore.Http; を追加. 次に ConfigureServices メソッドに

services.Configure<CookiePolicyOptions>(options =>
{
    options.Secure = CookieSecurePolicy.Always;
});

を追加する. 最後に Configure メソッドに

app.UseCookiePolicy();

を追加する. どの行に設定するのがベストなのかはわからないが、app.UseStaticFiles(); の次の行において動作することだけは確認した.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] 画面をキャプチャしてバイナリで保存する

0. 概要

Unityで大量のシミュレーション画像を生成してBMPで保存していたが、非常に取り回しが悪いので複数画像をバイナリ化して1つのファイルにしたい。そこで、PostRenderを使って描画される画面の左上ピクセルから順にRGBで並んだ配列をバイナリ化して1つのファイルに保存したので、その備忘録を以下に記す。

1. バイナリ画像化

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Capture : MonoBehaviour {
    Texture2D capture_display;
    string fileName = "screenshot\\image.bin";
    System.IO.BinaryWriter writer;
    byte[] yxrgb;
    int ary_size;

    // Use this for initialization
    void Start () {
        capture_display = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        writer = new System.IO.BinaryWriter(new System.IO.FileStream(fileName, System.IO.FileMode.Append));
        ary_size = Screen.width * Screen.height * 3;
        yxrgb = new byte[ary_size];
    }

    private void OnDestroy()
    {
        writer.Close();
    }

    private IEnumerator OnPostRender() {
            yield return new WaitForEndOfFrame();
            // capture the frame
            RenderTexture.active = Camera.main.targetTexture;
            capture_display.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
            capture_display.Apply();
            for (int i = 0; i < Screen.width; i++)
            {
                for (int j = 0; j < Screen.height; j++)
                {
                    int offset = ( (i * Screen.width) + (j) ) * 3;
                    yxrgb[offset + 0] = (byte)((int)(capture_display.GetPixel(i, j).r * 255));
                    yxrgb[offset + 1] = (byte)((int)(capture_display.GetPixel(i, j).g * 255));
                    yxrgb[offset + 2] = (byte)((int)(capture_display.GetPixel(i, j).b * 255));
                }
            }          
            writer.Write(yxrgb);
    }
}

yield return new WaitForEndOfFrame();を入れておかないと1フレーム遅れた画像が書き出されてしまうので気を付けること。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReactiveCommand の Subscribe で悩んでいた時の解決法

答え

こちらのサイトが参考になりました

using System;

ラムダを受け取る Subscribe の拡張メソッドは System 名前空間で定義されているんだそうです。ほげぇ。

そもそもなんで?

以前はXamarin.Formsで開発していたのですが、
Xamarinの新規コードを書く際はすでにusing System:されているため、なんの意識もせずにできるものだと思ってました。
今回はXamarinとは無関係のWPF開発だったので…。
ここ最近、参照先を設定する等もVisual studioの便利機能でぱぱっと解決してたので単なる考慮不足です…。

参考にしたサイト

【C#】ReactiveProperty全然分からねぇ!って人向けのFAQ集【修正済】

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RaspberryのDocker上でGPIOをWiringPiで使う

はじめに

RaspberryもGPIO(というかハードウェア全般)も初心者がDockerのコンテナでタクトスイッチのオンオフをConsoleに出力するだけのお話

環境

・Raspberry
・.NetCore 3.1(開発側)
・WiringPi
・実行はDocker(インストールしておいてください)

ソースはこちら

ハマりどころ

その1

現象

.NetCoreのruntimeコンテナでGPIOのアプリを起動したいので、マイクロソフトのイメージmcr.microsoft.com/dotnet/core/runtime:3.1-bionic-arm32v7を使ったところapt-getでWiringPiがインストールできませんでした(知っている方教えてください)

対処法

DockerfileにてラインタイムイメージにコンパイラをインストールしWiringPiをビルドすることで解決

その2

現象

RaspberryでGPIOを扱う場合に登場する/dev/gpioがコンテナ上ではアクセスができなくて困った。

対処法

Docerのコマンドに--deviceといパラメータがこれを使えばいいことが判明
だけど、今度はパーミッションエラーが発生
--privilegedコマンドを使えば回避できることが判明(特権モードで実行なので慎重に)

手順

開発側

  1. TackInvokerというフォルダを作成
  2. TackInvokerフォルダに移動
  3. dotnet new console
  4. Program.csを下記のファイルで置き換える
  5. TackInvokerフォルダの上に下記のDockerfileを配置
  6. docker build -t {自身のDockerHubID}/Tackinvoker:latest .
  7. docker push {自身のDockerHubID}/Tackinvoker:latest

Raspberry側

  1. docker run -it --rm --device /dev/gpiomem --privileged {自身のDockerHubID}/Tackinvoker:latest

素材達

Program.cs

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace TackInvoker
{
    class Program
    {

        public const int INPUT = 0;
        public const int OUTPUT = 1;

        public const int INT_EDGE_FALLING = 1;
        public const int INT_EDGE_RISING = 2;

        public const int Tack_PIN = 17;

        [DllImport("wiringPi")]
        extern static int wiringPiSetupGpio();

        [DllImport("wiringPi")]
        extern static void pinMode(int pin, int mode);

        [DllImport("wiringPi")]
        extern static void digitalWrite(int pin, int mode);


        [DllImport("wiringPi")]
        extern static int wiringPiISR(int pin, int edgeType, CallbackFunc func);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void CallbackFunc();

        static void Main(string[] args)
        {
            int ret = 0;

            // wiringPiのセットアップ
            wiringPiSetupGpio();

            // GPIO をINPUTに設定する.
            pinMode(Tack_PIN, INPUT);

            CallbackFunc callBackFunc = delegate () {
                Console.WriteLine("CallbackFunc is called !");

            };

            // GPIO がONになったらコールバック関数を呼ぶ.
            ret = wiringPiISR(Tack_PIN, INT_EDGE_RISING, callBackFunc);


            // 無限に待機する.
            Thread.Sleep(Int32.MaxValue);

        }
    }
}

Dockerfile

# ビルドイメージ
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build

WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.sln .

COPY TackInvoker/*.csproj ./  TackInvoker/

# copy everything else and build app

COPY TackInvoker ./TackInvoker/
RUN dotnet restore TackInvoker

WORKDIR /app/TackInvoker
RUN dotnet publish -c Release -o out

# ランタイムイメージ
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-bionic-arm32v7

# WiringPiをインストールする
RUN apt-get update
RUN apt-get install -y libi2c-dev
RUN apt-get install -y git-core
RUN apt-get install -y sudo
RUN apt-get install -y make
RUN apt-get install -y gcc
RUN git clone https://github.com/WiringPi/WiringPi.git
WORKDIR /WiringPi
RUN ./build

WORKDIR /app

COPY --from=build /app/TackInvoker/out ./

ENTRYPOINT ["dotnet", "TackInvoker.dll"]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MacのVisual Studio CodeでC#を実行する

Visual Studio CodeでC#を実行できるようにしようとするといろいろ嵌まったので,記録しておきたいと思います.

Visual Studio Codeをインストール

https://code.visualstudio.com
dmgをダウンロードして,appをコピーすることでインストール
スクリーンショット 2020-04-20 15.31.22.png

ターミナル作業

以下はターミナルでの作業になります.

Homebrewをインストール

本家サイトに掲載されているとおり,以下のコードを入力して実行します.

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

途中でパスワードを求められる(恐らく要管理者権限).

ScriptCSをインストール

$ brew install scriptcs

monoのパッケージなどもここで読み込まれている.

Visual Studio Codeの拡張機能を登録

スクリーンショット 2020-04-20 15.31.39.png

検索メニューからCode Runnerを検索して,選ぶ.

スクリーンショット 2020-04-20 15.32.46.png

「install」ボタンをクリックしてインストールする.

その他,日本語メニューの方がいい人は「Japanese Language Pack」も入れておく.

Code Runnerの設定

拡張機能の右下のギヤアイコンを右クリックして「拡張機能の設定」を開く
スクリーンショット 2020-04-21 11.57.58.png
スクリーンショット 2020-04-21 12.02.48.png

clearPreviousOutputやrunInTerminal,saveFileBeforeRunなどはチェックしておいた方がいいかもしれません.

「settings.jsonで編集」と書かれているリンクを開いて以下のコードを追加

"code-runner.executorMap": { "csharp": "scriptcs -script" },

この設定がないと"Unexpected named argument:"となって,嵌まります.
StackOverflowの記事

settings.jsonは,私の場合には上記でチェックしたものを含めて,こんな風になっていました.
スクリーンショット 2020-04-21 12.07.27.png

ファイルを保存して,設定完了.

テスト実行

C#コード

helloworld.cs
using System;

class test {
    public static void Main(){
        Console.WriteLine( "Hello,World" );
    }
}    
test.Main();
(base) Mac:~ user$ scriptcs -script "/Users/user/Desktop/helloworld.cs"
Hello,World
(base) Mac:~ user$ 
echoback.cs
using System;

class test {
    public static void Main(){
        string a = Console.ReadLine();
        Console.WriteLine( a );
    }
}    
test.Main();
(base) Mac:~ user$ scriptcs -script "/Users/user/Desktop/echoback.cs"
こんにちは
こんにちは
(base) Mac:~ user$ 

末尾のtest.Main()はCodeRunner.appのC#環境などでは不要ですが,この環境では書かないと動かないので注意しないといけません.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】引数を使ったボタンで好きな数字をテキストに表示する

環境

Unity 2019.3.7f1

はじめに

同じような処理のボタンが複数ある場合、
引数を使ったボタンでコードを簡略化できます。

こちらは一つの関数で処理しています。

方法

1.ボタンに割り当てる関数で引数を宣言する。
2.ボタン側で引数の入力値を設定

具体例

1~9の引数をそれぞれ設定したボタンを作成し、
ボタンを押すとテキストに
設定した数値が表示されるようにしてみましょう。

1.前準備
・ボタンを9つ作成
【Unity】オブジェクトを等間隔で配置する方法 Grid Layout Group
https://qiita.com/Maru60014236/items/56d2d53e0a80f1e65e94
で作ったボタン群を使います。
(内容:ボタン並べただけ)
image.png

・空のオブジェクトを作成
・新規スクリプト作成
・空のオブジェクトに作成したスクリプトを割り当てる

・テキストを作成
テキストは、見やすくするためこのように設定
・フォントサイズ50
・水平オーバーフロー Overflor
・垂直オーバーフロー Overflor
image.png

2.ボタンのテキスト変更
ボタンのテキストを1~9に変更。
テキストフォントサイズを50にする。
image.png

3.ボタンに割り当てる関数を作成
このようにコードを書きます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//UIを使うため追加

public class test : MonoBehaviour
{
    [SerializeField] private Text suuji_text;//Text型の変数suuji_textを宣言

    void Start()
    {        
    }

    //ボタンを押したら実行する関数 実行するためにはボタンへ関数登録が必要
    //int型の引数numberを宣言
    public void Push_Button(int number)
    {
        suuji_text.text =""+ number;//suuji_textに引数の数値を代入
    }
}

4.ボタンに関数割り当て
ボタンのクリック時のところに空のオブジェクトを割り当て
image.png

先程作成した関数を選択
image.png

 
数値入力欄が出現するので、
ここにボタンテキストに対応した数値を入力
image.png

それぞれのボタンで関数割り当て&数値入力を行ってください。

5.空のオブジェクトのスクリプトに前準備で作成したテキストをアタッチ
image.png

実行

おわりに

引数を使った関数でコードスッキリ!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】オブジェクトを等間隔で配置する方法 Grid Layout Group

環境

Unity 2019.3.7f1

はじめに

ボタンなどを等間隔で配置する方法です。
image.png

方法

1.整列させたいオブジェクト群をPanelオブジェクトに入れる
2.そのPanelオブジェクトにGrid Layout Group(グリッドレイアウトグループ)コンポーネントを追加
3.各種設定行う

具体例

実際にやってみましょう。

前準備
まずボタンを9つ作成します。
image.png

1.整列させたいオブジェクト群をPanelオブジェクトに入れる
パネルオブジェクト作成
image.png

今回Panelに色は不要なので透過を0にして透明にしておきます。
image.png
パネルの配下にボタンを入れる
image.png

2.PanelオブジェクトにGrid Layout Group(グリッドレイアウトグループ)コンポーネントを追加
Panelを選択
 
コンポーネントを追加
image.png

グリッドレイアウトグループを選択
image.png

3.各種設定行う
ボタンのサイズやセルの間隔などが調整できます。
今回はこのように設定しました。
image.png

できあがり!
image.png

おわりに

これで手作業での等間隔調整とはおさらばです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EntityFramework外部キー含めた複合インデックスの張り方

メモ程度に残しておきます。

以下のようなvirtualを使って外部キーとして定義されているCustomerモデルを持つRecordモデルがある。

/// <summary>
    /// 記録
    /// </summary>
    [Description("記録")]
    [Table("Records")]
    public class Record
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Record()
        {
        }

        // <summary>
        /// ID
        /// </summary>
        [Description("ID")]
        public long Id { get; set; }

        /// <summary>
        /// 記録日時
        /// </summary>
        [Description("記録日時")]
        public DateTime RecordAt { get; set; }

        /// <summary>
        /// 顧客
        /// </summary>
        [Required]
        public virtual Customer Customer { get; set; }
    }

    /// <summary>
    /// 顧客
    /// </summary>
    [Description("顧客")]
    [Table("Customers")]
    public class Customer
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Customer()
        {
        }

        // <summary>
        /// ID
        /// </summary>
        [Description("ID")]
        public long Id { get; set; }

        /// <summary>
        /// 名前(姓)
        /// </summary>
        [Description("名前(姓)")]
        [Required]
        [StringLength(20)]
        public string LastName { get; set; }

        /// <summary>
        /// 名前(名)
        /// </summary>
        [Description("名前(名)")]
        [Required]
        [StringLength(20)]
        public string FirstName { get; set; }
    }

このモデルにRecordAtとCustomer.Idの2つで複合indexを張りたいパターン。

/// <summary>
    /// 記録
    /// </summary>
    [Description("記録")]
    [Table("Records")]
    public class Record
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Record()
        {
        }

        // <summary>
        /// ID
        /// </summary>
        [Description("ID")]
        public long Id { get; set; }

        /// <summary>
        /// 記録日時
        /// </summary>
        [Description("記録日時")]
        [Index("IX_Customer_Id_RecordAt", 2)]
        public DateTime RecordAt { get; set; }

        /// <summary>
        /// CustomerプロパティのIdの値が入る
        /// </summary>
        [ForeignKey("Customer")]
        [Index("IX_Customer_Id_RecordAt", 1)]
        public long Customer_Id { get; set; }

        /// <summary>
        /// 顧客
        /// </summary>
        [Required]
        public virtual Customer Customer { get; set; }
    }

    /// <summary>
    /// 顧客
    /// </summary>
    [Description("顧客")]
    [Table("Customers")]
    public partial class Customer
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Customer()
        {
        }

        // <summary>
        /// ID
        /// </summary>
        [Description("ID")]
        public long Id { get; set; }

        /// <summary>
        /// 名前(姓)
        /// </summary>
        [Description("名前(姓)")]
        [Required]
        [StringLength(20)]
        public string LastName { get; set; }

        /// <summary>
        /// 名前(名)
        /// </summary>
        [Description("名前(名)")]
        [Required]
        [StringLength(20)]
        public string FirstName { get; set; }
    }

ForeignKey属性を付けると「外部キー制約のモデル名_プロパティ名」でCustomer.Idの値がセットされるプロパティを定義できる。
Index属性は(キー名, Order)で複合インデックスを張ることができる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む