ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

.NETでAccessをDBとして使う

必要になった理由

バッチでAccessのDBを読み取りSql Serverに更新するような要望が発生したため

Àccess DBを.NETで読み取る

以前のAccess2003(.mdb)の場合、「Microsoft.Jet.OLEDB.4.0」を使うらしいが、Access2010(.accdb)以降は、「Microsoft.ACE.OLEDB.12.0」をプロバイダとして使用するらしい

Microsoft Access Database Engine 2016インストール

以下のリンクからダウンロードした。
Download Microsoft Access Database Engine 2016 Redistributable from Official Microsoft Download Center 32bitバント64bit版があるが、64bitのOSには32bit版はインストール時エラーになった。

トラブル

Microsoft.ACE.OLEDB.12.0' プロバイダーはローカルのコンピューターに登録されていません。」
とエラーになるばかり、いろいろ調べて見ると、AniCpuやx64ではうまく動かず、実行時探しているバージョンは32bitだそう。
仕方ないので、64bit版は削除し、32bit版をインストールする。

AccessDatabaseEngine.exe /quiet

※64bit版OSでは「/quite」オプションで強制的にインストールが可能

一旦、これで接続は成功した。

ソース

プラットフォームはx86で作業しています。

using System.Data;
using System.Data.OleDb;

private const string CONNECTION_STRING = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\db\myDb.accdb";
private OleDbConnection _conn;

public void ExecuteSql()
{
    _conn = new OleDbConnection(CONNECTION_STRING);
    _conn.Open();

    OleDbCommand cmd =_conn.CreateCommand();
    cmd.CommandText = "SELECT * FROM MY_TABLE";

    DataTable dt;
    OleDbDataAdapter oda = new OleDbDataAdapter(cmd)
    oda.Fill(dt)

    _conn.Close();
}

パスワードがついているAccessの場合

「Jet OLEDB:Database Password」でパスワードを指定する

private const string CONNECTION_STRING = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\db\myDb.accdb;Jet OLEDB:Database Password=abc";

読取り専用モードでAccessを開きたい場合

「Mode」を指定してAccessを開く

指定値毎のモード

No Mode
Mode=1 Read
Mode=2 Share Deny None
Mode=3 ReadWrite
Mode=4 Share Deny None
Mode=5 Share Deny None
Mode=6 Share Deny None
Mode=7 Share Deny None
Mode=8 Share Deny Write
Mode=9 Share Deny None
Mode=10 Share Deny None
Mode=11 Share Deny None
Mode=12 Share Deny Read|Share Deny Write
Mode=13 Read|Share Deny Read|Share Deny Write
Mode=14 Share Deny None
Mode=15 Share Deny None
Mode=16 Share Deny None
Mode=17 Share Deny None
Mode=18 Share Deny None
Mode=19 ReadWrite|Share Deny None
private const string CONNECTION_STRING = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\db\myDb.accdb;Mode=1";

CodeLens解除、XAMLのUIデバックツールを非表示にする。

ソース上の参照数などの表示を非表示にする方法

VisualStudioのクラスやメソッドのソース上に参照数を表示する機能 f:id:haronoid:20190613103836p:plain

まあ、あると便利だが、ソースを表示するたびに行が広がり見づらくなったりするので、非表示にする。
「ツール」→「オプション」
「テキスト エディター」→「すべての言語」→「CodeLensを有効にする」のチェックを外す。
f:id:haronoid:20190613104020p:plain

XAML開発時に画面の上部に出る小さなウィンドウを非表示にする方法

「ツール」→「オプション」
「デバック」→「全般」→「XAMLのUIデバックツールを有効にする」のチェックを外す。
f:id:haronoid:20190613104720p:plain

ToggleButtonカスタマイズ

ToggleButtonを実装してみたものの、ControlTemplateが上手く動かなかったので、最終的に成功したパターンをメモ

と言っても、結局はStyleのTriggerで定義するだけでも解決だった

<ToggleButton x:Class="CustomToggleButton"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:local="clr-namespace:App1"
              mc:Ignorable="d" >
    <ToggleButton.Style>
        <Style TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
            <Setter Property="Background" Value="White" />
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="2" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Background" Value="Red"/>
                    <Setter Property="Foreground" Value="White"/>
                </Trigger>
                <Trigger Property="IsChecked" Value="False">
                    <Setter Property="Background" Value="White"/>
                    <Setter Property="Foreground" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ToggleButton.Style>
    <ToggleButton.Template>
        <ControlTemplate TargetType="{x:Type ToggleButton}">
            <Grid x:Name="MyButton" Background="Transparent">
                <Border x:Name="MyBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Background="{TemplateBinding Background}"/>
                <ContentPresenter x:Name="Presenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
            </Grid>
        </ControlTemplate>
    </ToggleButton.Template>
</ToggleButton>

既存ボタンのスタイルを継承しながら、カスタムボタン作成

ボタンとスタイルを定義

※StyleにBasedOnを指定しないと、既存のスタイルした表示してくれなかったので注意

<Button x:Class="CustomButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:App1"
             mc:Ignorable="d" >
    <Button.Style>
        <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
            <Setter Property="Background" Value="White" />
            <Setter Property="Foreground" Value="#E50012" />
            <Setter Property="BorderBrush" Value="#E50012" />
            <Setter Property="BorderThickness" Value="2" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
        </Style>
    </Button.Style>

ControlTemplateを設定する。

今回はVisualStateManagerを使いVisualState単位で状態を変更する。 Storyboardは基本アニメーション効果があるため、時間やFrom・Toの指定で変更効果を表示することが可能

    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
                <!--ボタンは基本四角い状態であるため、せっかく丸いBorderにしてもはみ出て角が見えていたため透明にした-->
            <Grid x:Name="MenuButton" Background="Transparent">
                <!--ボタンの枠線:CornerRadiusで丸みを設定できる。-->
                <Border x:Name="MenuBorder" BorderBrush="#E50012" BorderThickness="3" CornerRadius="10" Background="{TemplateBinding Background}"/>
                <!--ボタン内の本体?-->
                <ContentPresenter x:Name="Presenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup Name="CommonStates">
                        <VisualState Name="Normal" />
                        <VisualState Name="MouseOver">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="MenuBorder"
                                       Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
                                       Duration="00:00:00.1"
                                       To="LightPink" />
                                <ColorAnimation Storyboard.TargetName="Presenter"
                                       Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
                                       Duration="00:00:00.1"
                                       To="#E50012" />
                            </Storyboard>
                        </VisualState>
                        <VisualState Name="Pressed">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="MenuBorder"
                                       Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
                                       Duration="00:00:00.1"
                                       To="#E50012" />
                                <ColorAnimation Storyboard.TargetName="Presenter"
                                       Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
                                       Duration="00:00:00.1"
                                       To="white" />
                                <ThicknessAnimation Storyboard.TargetName="MenuBorder"
                                            Storyboard.TargetProperty="Margin"
                                            Duration="00:00:00.1"
                                            To="0,0,0,0" />
                            </Storyboard>
                        </VisualState>
                        <VisualState Name="Disabled">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="MenuBorder"
                                       Storyboard.TargetProperty="BorderBrush.(SolidColorBrush.Color)"
                                       To="Gray"/>
                                <ColorAnimation Storyboard.TargetName="Presenter"
                                       Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
                                       To="Gray"/>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Grid>
        </ControlTemplate>
    </Button.Template>

VisualState関連参考

以下のリンクから、全コントロール分のスタイルテンプレートを参照可能 コントロールのスタイルとテンプレート | Microsoft Docs

画像ボタンを作成してみる。

カスタムボタンを定義

とりあえず、カスタムボタンを定義し、基本的にスタイルのみ設定していみる。

<Button x:Class="MyButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:App1"
             mc:Ignorable="d" >
    <Button.Style>
        <Style TargetType="Button" >
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="FontSize" Value="25" />
            <Setter Property="FontWeight" Value="Bold" />
        </Style>
    </Button.Style>

ControlTemplateでボタンの内部構成とTriggerで表示・非表示を切り替える。

状態ごとに、表示を切り替えているだけだが、上手く動いた

    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Grid>
                <Image Name="Normal" Source="/App1;component/Images/btn_normal.png"/>
                <Image Name="MouseOver" Source="/App1;component/Images/btn_mouseover.png" Visibility="Hidden"/>
                <Image Name="Pressed" Source="/App1;component/Images/btn_pressed.png" Visibility="Hidden"/>
                <Image Name="Disabled" Source="/App1;component/Images/btn_gray.png" Visibility="Hidden"/>
                <TextBlock Name="NormalText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Text="{TemplateBinding Content}"/>
                <TextBlock Name="PressedText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="White" Text="{TemplateBinding Content}"  Visibility="Hidden"/>
                <TextBlock Name="DisabledText" Margin="0,5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="Gray" Text="{TemplateBinding Content}"  Visibility="Hidden"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsPressed" Value="True">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="NormalText" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="PressedText" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="MouseOver" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="NormalText" Property="Visibility" Value="Hidden"/>
                    <Setter TargetName="Disabled" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="DisabledText" Property="Visibility" Value="Visible"/>
                </Trigger>
            </ControlTemplate.Triggers>
           
        </ControlTemplate>
    </Button.Template>

batファイル用コマンドメモ

変数使用

SET HOGE=abc
ECHO %HOGE%

日付取得

日付はシステムの日付フォーマットで表示されるため、ファイル名などに使うには部分を取得し、合体させる必要がある。

ECHO %date%
YYYY/MM/DD
ECHO %time%
HH:MM:SS.SS
ECHO  %date:~0,4%%date:~5,2%%date:~8,2%
YYYYMMDD

for分

for %%アルファベット1文字 in (対象) do コマンド

for %%i in (*.log) do (
  echo %%i
)

遅延環境変数

batファイル内の変数への値設定と読み込むタイミングにより、変数の値が正しくならないため、遅延環境変数を設定する。 遅延環境変数は「!」+「変数名」+「!」でループ内で実行時に取得するようになる。

setlocal enabledelayedexpansion
for %%f in (01,02,03,04,05) do (
    SET FNAME=%%f.log
    echo create file : !FNAME!
    echo !FNAME! > !FNAME!
)
endlocal

DataGrid 操作についてメモ

DataGridTextColumn

セルのスタイルを編集する場合 DataGridTextColumn.ElementStyleを利用し、スタイルを指定する

<DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Header="ヘッダー名" Binding="{Binding MyDate,StringFormat=yyyy/MM/dd}" Width="100">
      <DataGridTextColumn.ElementStyle>
        <Style TargetType="TextBlock">
          <Setter Property="TextAlignment"  Value="Center" />
        </Style>
      </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>
  </DataGrid.Columns>
</DataGrid>

セルをカスタマイズ

DataGridTemplateColumnを利用し、DataTemplateを配置する

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Command="{Binding ButtonActionCommand}" >押す/Button>
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

編集可能セルを設定する

DataGridTextColumnでもIsReadOnlyがFalseの場合、ダブルクリックで編集可能だが、カスタムしたい場合、CellEditingTemplateを使用する。 ただし、表示時のTempleteも指定しないと表示されないため、CellTemplateも設定する必要がある。 ※DataGridTemplateColumnではCellEditingTemplateの中にバインドしたものだけが正しくSet処理が実行される。

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Text1}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
      <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Text1}"/>
        </DataTemplate>
      </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

セルダブルクリックイベントをCommandで受け取る方法

DataGrid.InputBindingsにMouseBindingを設定し、イベントアクションをCommandにつなぐ

<DataGrid>
  <DataGrid.InputBindings>
    <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding GridMouseDoubleClickCommand}"/>
  </DataGrid.InputBindings>
</DataGrid>

ヘッダー表示をカスタマイズする。

HeaderTemplateを利用し、ヘッダーを2行表示する。

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="ヘッダー名" Width="100">
      <DataGridTemplateColumn.HeaderTemplate>
        <DataTemplate>
          <StackPanel>
            <TextBlock Text="ヘッダー1行" />
            <Separator/>
            <TextBlock Text="ヘッダー2行" />
          </StackPanel>
        </DataTemplate>
      </DataGridTemplateColumn.HeaderTemplate>
  </DataGrid.Columns>
</DataGrid>