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>
CSVファイルからのBULK INSERT
CSVファイルからSQL ServerのTableへ高速でデータを投入する
私用場面は色々あるが、とりあえず、スキーマ間でデータを移動する場合を想定します。
復元もとDBからデータを抽出するためのSQLをファイルに記載します。
output.sql
SET NOCOUNT ON ; SELECT * FROM [dbo].[MyTable];
コマンドラインからSqlファイルのSQLを実行し、CSVファイルに吐き出します。
SQLCMD -S localhost -U sa -P {password} -d {dbname} -i output.sql -s, -W -h -1 -o output.csv
出力されたファイルを復元先DBからアクセス可能なパスにおいてBulk Insertを実行します。
bulk insert dbo,MyTable from '\\c\work\output.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' );
ADO.NET Entity Data Model(edmx)で生成した接続文字列をコードで生成する。
ADO.NET Entity Data Model(edmx)で生成した場合
app.config内部にmetadataを含むConnectionStringが生成される。せっかく自動生成したEntity Data Modelを再利用しながら、ConnectionStringをConfigファイルから隠したいため、コードベースで生成する必要があった
DataContext修正
edmxの内部のDbContextクラスにDbConnectionをもらうコンストラクタを追加する。
Partial Public Class DbEntities Inherits DbContext Public Sub New() MyBase.New("name=DbEntities") End Sub ' 追加 Public Sub New(conn As DbConnection) MyBase.New(conn, True) End Sub End Class
追記:DALの更新時、追加したコンストラクタが消えてしまう事がわかったため、別のAppDbContextクラスで対応
Public Class AppDbContext Inherits DbContext Public Sub New(conn As Common.DbConnection) MyBase.New(conn, True) End Sub ''' ''' 以下の部分はDbEntitiesの自動生成プロパティをコピー・ペーストしてあげる。 ''' End Class
DBコネクション処理修正
' Initialize the connection string builder Dim sqlBuilder As New SqlConnectionStringBuilder() With { .DataSource = "localhost", .InitialCatalog = "testdb", .UserID = "sa", .Password = "mypassword", .IntegratedSecurity = True } ' Initialize the EntityConnectionStringBuilder. Dim entityBuilder As New EntityConnectionStringBuilder() With { .Provider = "System.Data.SqlClient", .ProviderConnectionString = sqlBuilder.ToString(), .Metadata = "res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl" } _dbContext = New DAL.AppDbContext(New EntityConnection(entityBuilder.ToString()))