BooMark-プログラミングや美術のあれこれ-

半歩ずつでも進めばよろし

Prism、XAML関連記事(ブックマーク)

▽▼Prismとは?▼▽

WPFアプリなどをMVVMパターンで作成するためのフレームワーク
Visual StudioでPrism Template Packをインストールすることで使える。
 

▽▼XAMLとは?▼▽

マークアップ言語。WPFのUI担当。
XAMLを使わないで、C#でもWPFアプリは作れる。

▽▼ブックマーク▼▽

elf-mission.net
Viewを作成したときに、行始めから記述されているおまじないなど。解説が丁寧。 


atmarkit.itmedia.co.jp
XAMLの基本的な(深い)話。


www.niwaka-plus.com
Prism Template Pack、デザインフレームワーク、Reactive Propertyのインストール。環境構築周りがまとめてあるのでやってみたい。


 

【WPF】任意のイベントでコマンド実行する

任意のイベントで任意のコマンド実行する方法。

▽▼完成図▼▽

1.ウィンドウ初期表示
f:id:boomark:20220308231047p:plain

2.ウィンドウ内を左クリックしたときに、ユーザーコントロール遷移
f:id:boomark:20220308231137p:plain


▽▼ソースコード▼▽

■MainWindow.xaml

 (以下が必要)
・xmlns:prism="http://prismlibrary.com/"
・xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
 EventNameに"Loaded"とすれば画面読み込み時にコマンド(MouseLeftButtonDownCmd)を実行する。
 ※EventNameはインテリセンスが効かないので調べて使おう

<Window x:Class="MyWorkProject.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeftButtonDown">
            <prism:InvokeCommandAction Command="{Binding MouseLeftButtonDownCmd}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    
    <Grid>
        <StackPanel>
            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </StackPanel>
    </Grid>
</Window>
■MainWindowViewModel.cs
using MyWorkProject.Views;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;

namespace MyWorkProject.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private IRegionManager _regionManager;

        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public DelegateCommand MouseLeftButtonDownCmd { get; }

        public MainWindowViewModel(IRegionManager regionManager)
        {
            _regionManager = regionManager;
            MouseLeftButtonDownCmd = new DelegateCommand(ShowWorkA);
        }

        public void ShowWorkA()
        {
            _regionManager.RequestNavigate("ContentRegion", nameof(WorkA));
        }
    }
}
■WorkA.xaml
<UserControl x:Class="MyWorkProject.Views.WorkA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <StackPanel>
            <TextBlock Text="WorkA" FontSize="20" FontWeight="Bold"/>
        </StackPanel>
    </Grid>
</UserControl>
■WorkAViewModel.cs
using Prism.Mvvm;

namespace MyWorkProject.ViewModels
{
    public class WorkAViewModel : BindableBase
    {

        public WorkAViewModel()
        {
        }
    }
}

【WPF】Resourcesを使って共通の設定をする

コントロールをまとめて設定したいときにApplication.Resources、Window.Resourcesを使うと便利。

▽▼完成図▼▽

f:id:boomark:20220306235243p:plain


▽▼ソースコード▼▽

■App.xaml
prism:PrismApplication x:Class="MyWorkProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	     xmlns:prism="http://prismlibrary.com/"
             xmlns:local="clr-namespace:MyWorkProject">
    <Application.Resources>
        <SolidColorBrush x:Key="Grean" Color="PaleGreen"/>
    </Application.Resources>
</prism:PrismApplication>
■MainWindow.xaml
<Window x:Class="MyWorkProject.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <Window.Resources>
        <SolidColorBrush x:Key="Grey" Color="DarkGray"/>
        <Style TargetType="Button">
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="Background" Value="Beige"/>
            <Setter Property="Foreground" Value="Blue"/>
            <Setter Property="FontWeight" Value="Heavy"/>
        </Style>
    </Window.Resources>
    
    <Grid>
        <StackPanel>
            <Button Content="ボタン(App.Resources&lt;SolidColorBrush&gt;, Win.Resources&lt;Style&gt;)"
                    Background="{StaticResource Grean}"/>
            <Button Content="ボタン(Win.Resources&lt;SolidColorBrush&gt;, &lt;Style&gt;))"
                    Background="{StaticResource Grey}"/>
            <Button Content="ボタン(Win.Resources&lt;Style&gt;)"/>
            <Label Content="ラベル"
                   Background="{StaticResource Grey}"/>
            <TextBlock Text="テキストブロック"
                       Background="{StaticResource Grey}"/>
            <TextBox Text="テキストボックス"
                     Background="{StaticResource Grey}"/>

            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </StackPanel>
    </Grid>
</Window>

☆Application.Resources:アプリ全体の共通設定
☆Window.Resources:画面(XAML)内の共通設定
☆上記Resouces内でStyleタグを使うことで、コントロールの種類ごとに設定できる。(上記だと、Buttonの場合に文字の水平位置、背景色、文字色、文字の太さを適用)

【WPF】コンテキストメニューの表示方法

WPFコンテキストメニューを表示する方法。

▽▼完成図▼▽

①Buttonコントロールコンテキストメニューを設定して表示
f:id:boomark:20220306000015p:plain

②<Window.ContextMenu>でコンテキストメニューを設定して表示
f:id:boomark:20220306000022p:plain

③ボタン以外のコントロールコンテキストメニューを表示
f:id:boomark:20220306000027p:plain

▽▼ソースコード▼▽

■MainWindow.xaml

<Window x:Class="MyWorkProject.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">

    <!--②-->
    <Window.ContextMenu>
        <ContextMenu>
            <MenuItem Header="共通コンテキストメニュー"/>
        </ContextMenu>
    </Window.ContextMenu>

    <Grid>
        <StackPanel>
            <!--①-->
            <Button Content="ボタン">
                <Button.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="ボタン子"/>
                    </ContextMenu>
                </Button.ContextMenu>
            </Button>
            
            <!--②-->
            <Button Content="ボタン(共通)"/>
            
            <!--③-->
            <Label Content="ラベル"/>
            <TextBlock Text="テキストブロック"/>
            <TextBlock Text="テキストブロック"/>
            <TextBox Text="テキストボックス"/>

            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </StackPanel>
    </Grid>
</Window>

☆<Window.ContextMenu>を設定すると、コンテキストメニューを個別設定した箇所(上記だと「ボタン」)以外で右クリックしてコンテキストメニューを表示するみたい。
コンテキストメニューは、ボタン以外にも設定できる。

【C#】(未解決)SQLiteで「'SQLite.Interop.dll' を読み込めません」

▽▼起こったこと▼▽

SQLiteのSQLiteConnection生成のあたりで実行時にエラーが発生する。


■発生場所

using (var connection = 
    new SQLiteConnection(@"Data Source=C:\Users\(略)\〇〇.db;Version=3;"))

■エラー内容

例外がスローされました: 'System.DllNotFoundException' (System.Data.SQLite.dll の中)
型 'System.DllNotFoundException' の例外が System.Data.SQLite.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした
DLL 'SQLite.Interop.dll' を読み込めません:指定されたモジュールが見つかりません。 (HRESULT からの例外:0x8007007E)

SQLite.Interop.dllが必要だけれど探せていないらしい。
SQLiteが使えているプロジェクトを見ると
binフォルダ(の中のDebugフォルダ)にx86、x64フォルダがあり、その中にそれぞれSQLite.Interop.dllが入っている。
両フォルダをSQLiteがエラーのプロジェクトにコピペしたところSQLiteに接続できるようになった。

▽▼疑問▼▽

x86、x64フォルダはどうして作られなかったのか?

今回WPFのプロジェクトでエラーが起きた。
Nugetパッケージをインストールしてもpackages.configは作られないので調べてみると、プロジェクトファイル(〇〇.csproj)にPackageReferenceがある。
パッケージ参照にはPackageReferenceを採用しているぽい。
これだとSQLite.Interop.dllは作られないのかな

■〇〇.csproj

  <ItemGroup>
    <PackageReference Include="System.Data.SQLite">
      <Version>1.0.115.5</Version>
    </PackageReference>
  </ItemGroup>

packages.configがあるWindowsフォームのプロジェクトにはx86、x64フォルダができた。
何がだめなんだろう。SQLiteはPackageReferenceには対応していない..? わからない。。

■packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="EntityFramework" version="6.4.4" targetFramework="net461" />
  <package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.115.5" targetFramework="net461" />
  <package id="System.Data.SQLite" version="1.0.115.5" targetFramework="net461" />
  <package id="System.Data.SQLite.Core" version="1.0.115.5" targetFramework="net461" />
  <package id="System.Data.SQLite.EF6" version="1.0.115.5" targetFramework="net461" />
  <package id="System.Data.SQLite.Linq" version="1.0.115.5" targetFramework="net461" />
</packages>


▽ヒント
sqlite - C# SQLiteを操作するクラスをクラスライブラリ化したときにInterop.dllを要求される点について - スタック・オーバーフロー

▽関連
プロジェクト ファイルの NuGet PackageReference | Microsoft Docs

【WPF】画面遷移の方法_Navigation

RegionManagerのナビゲーションを使って画面遷移する方法。

▽▼完成図▼▽

1.メイン画面表示
f:id:boomark:20220303205215p:plain
2.「ボタンA」押下後
f:id:boomark:20220303205224p:plain

▽▼ソースコード▼▽

1.メイン画面にボタンを設置
■MainWindow.xaml

<Window x:Class="MyWorkProject.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolVisibilityConverter" ></BooleanToVisibilityConverter>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Button Content="ボタンA"
                    Command="{Binding CmdAButton}"/>
            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </StackPanel>
    </Grid>
</Window>

2.遷移先画面
■WorkA.xaml

<UserControl x:Class="MyWorkProject.Views.WorkA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <StackPanel>
            <TextBlock Text="WorkA" FontSize="20" FontWeight="Bold"/>
        </StackPanel>
    </Grid>
</UserControl>

3.App.xamlのコードビハインドにナビゲーション対象の画面(遷移先画面)を追加
■App.xaml.cs

using MyWorkProject.Views;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;

namespace MyWorkProject
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // 表示する画面を追加
            containerRegistry.RegisterForNavigation<WorkA>();
        }
    }
}

4.画面遷移処理
■MainWindowViewModel.cs

using MyWorkProject.Views;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;

namespace MyWorkProject.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private IRegionManager _regionManager;

        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public DelegateCommand CmdAButton { get; }

  // RegionManagerを引数に設定
        public MainWindowViewModel(IRegionManager regionManager)
        {
            _regionManager = regionManager;
            CmdAButton = new DelegateCommand(ShowWorkA);
        }

        public void ShowWorkA()
        {
            // MainWindow.xamlの"ContentRegion"の箇所に、WorkAを表示
            _regionManager.RequestNavigate("ContentRegion", nameof(WorkA));
        }
    }
}

以上です!

【Excel2016】図形の範囲選択、シート内全選択

ドキュメント作成していて、複数行まとめて消したら図形だけ残った。
Ctrl押しながらクリックすると複数選択できるけれど、一気に選択して消したい。。そんなとき

①「オブジェクトの選択」をクリック
f:id:boomark:20220301204431p:plain

②選択したい図形を囲む
f:id:boomark:20220301204436p:plain

③選択状態になる
f:id:boomark:20220301204440p:plain

また、シート内の全図形(オブジェクト)を選択するには、図形を1つ選択した状態でCtrl+Aをする。