- 投稿日:2021-01-23T22:19:05+09:00
WPFでMahAppsとMaterialDesignを使用しているとDark, Lightモードで表示がうまくいかなくなる
はじめに
以前MahAppsでカラー設定の保存と利用という記事を書きましたが、そこでテーマをDarkモードにした場合、文字が白抜きになるのはずなのですが、コントロールによって黒文字のままだったり、白背景に白文字という現象が起きました。
問題
本当はこう(Dark)なのに
それがこうなる(一番左のListBoxが黒文字)
Lightの場合本当はこうなるはず
それがこうなる(罫線が見えない(白い?))
解決
以前の記事でSetThemeAndColorを呼び出していましたが、その前に以下のようにApplyBaseThemeを呼び出して設定するとうまくいきました。
using MaterialDesignThemes.Wpf; private readonly PaletteHelper _paletteHelper = new PaletteHelper(); public void ApplyBaseTheme(bool isDark) { ITheme theme = _paletteHelper.GetTheme(); IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme(); theme.SetBaseTheme(baseTheme); _paletteHelper.SetTheme(theme); }MaterialDesign側のテーマ設定を先に行って、それから通常のテーマ設定をするとうまくカラーが設定できるようです。
- 投稿日:2021-01-23T21:26:08+09:00
EntityFramewofk Coreで自動採番となっているテーブルで指定のIDを追加したい
はじめに
現在利用しているアプリを新規アプリに変更するにあたってSQL Serverに新しくデータベースを作って、そこに元のデータをいれようと思っていました。
テーブルをコードファーストで作っていたのですが、これだと旧テーブルから新テーブルにデータを移行する際に、IDが変わってしまうという問題がありました。
そこで、いろいろと調べていると、SET IDENTITY_INSERT [table名] ON を行えばいいということが分かり実装してみました。問題が起きました
Master_Staff(旧テーブル) ⇒ Main_User(新テーブル)
蛇足ですが、昨今の"Master"は使わないようにしようという流れにあわせて、新規アプリでテーブル名を変更することにしました。internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs) { await Task.Run(() => { foreach (var s in MasterStaffs) { dbContext.Main_Users.Add(new Main_User() { Main_UserId = s.Master_StaffId, UserName = s.StaffName, }); } dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON"); dbContext.SaveChanges(); dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF"); } }SqlException: IDENTITY_INSERT が OFF に設定されているときは、テーブル 'Main_Users' の ID 列に明示的な値を挿入できません。
というエラーが起きました。解決
いろいろと調べると、Microsoft Documentに生成されるプロパティに明示的な値を設定するというページがありました
そこにあるSampleは以下の通りusing (var context = new EmployeeContext()) { context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" }); context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" }); context.Database.OpenConnection(); try { context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees ON"); context.SaveChanges(); context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees OFF"); } finally { context.Database.CloseConnection(); } }どうやら、同じ接続内でSET IDENTITY_INSERTを行わないとエラーになるようでした。
ということで以下のようにコードを変更したらうまくいきました。internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs) { await Task.Run(() => { foreach (var s in MasterStaffs) { dbContext.Main_Users.Add(new Main_User() { Main_UserId = s.Master_StaffId, UserName = s.StaffName, }); } //ExecuteSqlRawとSaveChangesの部分を以下のように変更しました。 dbContext.Database.OpenConnection(); try { dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON"); dbContext.SaveChanges(); dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF"); } finally { dbContext.Database.CloseConnection(); } } }分かってしまえばなんてことないことですが、分かるまでは「なんで?」と思って、他にいろいろと原因を探して、無駄な時間を費やしてしまいます。
同じように困っている人がいれば、参考となればと思います。
- 投稿日:2021-01-23T17:40:30+09:00
SemaphoreSlimの使い方
同時に仕事をできる机(Task)の数を制限するのがSemaphoreSlimです。
基本
//机を2つ用意 SemaphoreSlim ss = new SemaphoreSlim(2); //机が1つ埋まる ss.Wait(); //机がもう1つ埋まる ss.Wait(); //机を1つだけ空ける ss.Release(1); //空いてる机の数を確認 Console.WriteLine(ss.CurrentCount); //実行結果は、1簡単な例
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { SemaphoreSlim ss = new SemaphoreSlim(0); //最初は、机を1つも作らない ss.Release(1); //机を1つだけ追加 //机が1つしかないので、作業1だけが実行される Task task1 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業1");}); Task task2 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業2");}); //1つしかない机は、作業1で埋まっているので、0 Console.WriteLine( ss.CurrentCount); Console.ReadLine(); } }引数
SemaphoreSlim ss = new SemaphoreSlim(1, 6);第1引数は、机の数(後から追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。Waitと、WaitAsyncの違い
using System; using System.Threading.Tasks; using System.Threading; using System.Collections.Generic; class Program { static void Main(string[] args) { Sub(); Console.WriteLine("main"); //A Console.ReadLine(); } public static async Task Sub() { SemaphoreSlim ss = new SemaphoreSlim(2); List<Task> list = new List<Task>(); int num = 10; while(num-- > 0) { await ss.WaitAsync(); //B Aが先に実行される(非同期) //ss.Wait(); //C Aが後に実行される(同期) list.Add( Task.Run( () => { Thread.Sleep(100); Console.WriteLine("-"); ss.Release(); })); } await Task.WhenAll(list); } }Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。キャンセル
CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。
つづく・・・
- 投稿日:2021-01-23T17:40:30+09:00
SemaphoreSlimのかんたんな使い方
同時に仕事をできる机(Task)の数を制限するのがSemaphoreSlimです。
基本
//机を2つ用意 SemaphoreSlim ss = new SemaphoreSlim(2); //机が1つ埋まる ss.Wait(); //机がもう1つ埋まる ss.Wait(); //机を1つだけ空ける ss.Release(1); //空いてる机の数を確認 Console.WriteLine(ss.CurrentCount); //実行結果は、1簡単な例
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { SemaphoreSlim ss = new SemaphoreSlim(0); //最初は、机を1つも作らない ss.Release(1); //机を1つだけ追加 //机が1つしかないので、作業1だけが実行される Task task1 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業1");}); Task task2 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業2");}); //1つしかない机は、作業1で埋まっているので、0 Console.WriteLine( ss.CurrentCount); Console.ReadLine(); } }引数
SemaphoreSlim ss = new SemaphoreSlim(1, 6);第1引数は、机の数(後から追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。Waitと、WaitAsyncの違い
using System; using System.Threading.Tasks; using System.Threading; using System.Collections.Generic; class Program { static void Main(string[] args) { Sub(); Console.WriteLine("main"); //A Console.ReadLine(); } public static async Task Sub() { SemaphoreSlim ss = new SemaphoreSlim(2); List<Task> list = new List<Task>(); int num = 10; while(num-- > 0) { await ss.WaitAsync(); //B Aが先に実行される(非同期) //ss.Wait(); //C Aが後に実行される(同期) list.Add( Task.Run( () => { Thread.Sleep(100); Console.WriteLine("-"); ss.Release(); })); } await Task.WhenAll(list); } }Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。キャンセル
CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。
つづく・・・
- 投稿日:2021-01-23T17:40:30+09:00
かんたんな「SemaphoreSlim」の使い方
同時に仕事をできる机(
Task
)の数を決めるのが、SemaphoreSlim
です。
基本
//机を2つ用意 SemaphoreSlim ss = new SemaphoreSlim(2); //机が1つ埋まる ss.Wait(); //机がさらに1つ埋まる ss.Wait(); //2つとも埋まった机のうち、1つだけ空ける ss.Release(1); //空いてる机の数を確認 Console.WriteLine(ss.CurrentCount); //実行結果は、1
Wait
で机を使う。
Release
で机を空けるか、新しい机を用意する。
CurrentCount
で机の数を確認かんたんな例
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { SemaphoreSlim ss = new SemaphoreSlim(0); //最初は、机を1つも作らない ss.Release(1); //机を1つだけ追加 //机が1つしかないので、作業1だけが実行される Task task1 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業1");}); Task task2 = Task.Run(() =>{ss.Wait(); Console.WriteLine("作業2");}); //1つしかない机は、作業1で埋まっているので、0 Console.WriteLine( ss.CurrentCount); Console.ReadLine(); } }Taskを実行しようとしても、空いてる机の数しか実行されない
引数
SemaphoreSlim ss = new SemaphoreSlim(1, 6);第1引数は、机の数(あとから追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。SemaphoreSlim ss = new SemaphoreSlim(1);引数は机の数(最大数は未設定なので、あとからいくらでも追加できる)
Waitと、WaitAsyncの違い
using System; using System.Threading.Tasks; using System.Threading; using System.Collections.Generic; class Program { static void Main(string[] args) { Sub(); Console.WriteLine("main"); //A Console.ReadLine(); } public static async Task Sub() { SemaphoreSlim ss = new SemaphoreSlim(2); List<Task> list = new List<Task>(); int num = 10; while(num-- > 0) { await ss.WaitAsync(); //B Aが先に実行される(非同期) //ss.Wait(); //C Aが後に実行される(同期) list.Add( Task.Run( () => { Thread.Sleep(100); Console.WriteLine("-"); ss.Release(); })); } await Task.WhenAll(list); } }Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。キャンセル
CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。
つづく・・・
- 投稿日:2021-01-23T14:30:16+09:00
Unity:Addressable でコンテンツをダウンロード
Addresablesでコンテンツをサーバからダウンロードする方法
環境
OS macOS 10.15.7
Unity 2019.4.2f1
Addressable 1.16.15
PackageManagerからAdressablesをインストール
WindowメニューからAsset Management->Addressables->Groupsを選択
Create Addressables Settingsをクリック
オブジェクトを配置する。オブジェクトは一度ProjectにドラッグしPrefabにする。この例では「Object」と名前をつけた。
PrefabにしたオブジェクトはHierarchyから削除する。
PrefabはAddressableにチェックを入れる。
カラのGameObjectを生成し、その中に下記のスクリプトを記述する。ここではファイル名を「LoadScript」とした。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; public class LoadScript : MonoBehaviour { public AssetReference reference; // Start is called before the first frame update void Start() { reference.InstantiateAsync(); } }上記のスクリプトのInspecterには下図のようなUIが表示されるので、リモートからロードするPrefabを選択する。
上記のUIがInspectorに表示されない場合は、Project WindowでRefleshする。
AdressableAssetSettingのInspectorでCatalogの設定をおこなう。
Assets>AddresableAssetsDataの中にあるAdressableAssetSettingをクリックしてInspectorを表示する。
「Build Remote Catalog」にチェックを入れる。
「Build Remote Caralog」はRemoteBuildPathを選択。
「LoadPath」はRemoteLodePathを選択。
ここではlocalhostのStandaloneOSXフォルダを参照するようになっている。
LoadPathのURLを変更する際にはWindow>Addressable Management>Addresbles>Profilesを開きRemoteLoadPathのURLを変更する。
リモートサーバにアップするファイルのビルドを行う。
Play Mode ScriptのUse Existing Buildを選択
Build>New Build> Default Build Scriptを選択肢ビルドする。
プロジェクトのフォルダ内にSarverDataフォルダが出来ているはず。
その中にBuildTarget名のフォルダをアプリが参照するディレクトリにコピーする。
macOSの場合httpServerが/Library/WebServer/Documentsを参照するので下記の様になる
最後にアプリをBuild and Runを実行する。
- 投稿日:2021-01-23T00:50:21+09:00
岩永さんの配信の「Visual Studio 16.9 Preview 3 リリース (C# 10.0 追加予定機能ちょっとあり)」に参加してきました
Visual Studio 16.9 Preview 3 リリース (C# 10.0 追加予定機能ちょっとあり)
今回も岩永さんの動画にお邪魔させてもらいました。
岩永さんの配信は 1 つの配信に対して 1 Issue という感じになっています。なので、Issue を見るとポイントになった箇所のコードとかが簡単な説明と共に書いてあるので、Issue を見るだけでも内容がわかって忙しい人にはお勧めです!(一番はライブで見るですけど!)
https://github.com/ufcpp-live/UfcppLiveAgenda/issues/24
今回のおすすめポイント
自分的には最後にあった XALM で DataContext プロパティに設定する ViewModel を生成してくれるところと、PInvoke のコードを生成している CsWin32 です。
該当コメントへの直リンク
XAML からの ViewModel 生成。INotifyPropertyChanged も生成してる。プロパティ生成もあった。
まとめ
ということで、今後も配信に参加したらこんな感じで軽いまとめを書いてみようと思います。