WPF 外部ライブラリに宣言されているリソースディクショナリの使用方法
いつも書き方を忘れるのでメモ。
下の画像のようにプロジェクトResourceDictionaryServe内にリソースディクショナリMyResourceDictionaryがあったとして
これをResourceDictionaryClientで使いたいとなった場合の記述は以下の通り
ResourceDictionaryのSourceプロパティに
"/{アセンブリ名};component/{リソースディクショナリ名}"
と記述する。
WPFのVisibilityとIsVisibleの違い
twitterではぶつぶつ独り言を呟いているけど、
ブログの方は半年以上なにも書いてなかったのか・・・
ここしばらくWPFやC#で色々と痛い思いをしてるので、
忘れないように少しずつブログに吐き出す習慣をつけるようにしたい。
ソースやXAMLも載せた方が良いのだろうけど、
手間かけるとどうせ飽きるので適当に書きます。
で、掲題の話、
以前この違いをはっきり意識せずにコーディングしてて成大にバグったのでメモ
端的にいうと
Visibility→この要素の可視状態
IsVisible→この要素が表示されているか否か
ということ。
WPF ボタンのカスタマイズ方法概略
ボタン側のXAML
ボタンのXAML、Buttonクラスを継承して記述、コードビハインドは無し。
VSでユーザーコントロール(WPF)を追加して派生元をUserControlからButtonに変更したものを編集
<Button x:Class="WpfApp1.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:WpfApp1" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" OverridesDefaultStyle="True" FocusVisualStyle="{x:Null}" > <Button.Template> <ControlTemplate TargetType="Button"> <Grid> <Border x:Name="ButtonVisual" BorderBrush="DimGray" BorderThickness="2" Background="AliceBlue" > <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" /> </Border> <Border x:Name="MaskOnPressed" Background="Black" Opacity="0.1" Visibility="Hidden" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="true"> <Setter TargetName="ButtonVisual" Property="BorderBrush" Value="MidnightBlue"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="ButtonVisual" Property="Background" Value="Lavender"/> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" Value="0.5"/> </Trigger> <Trigger Property="IsPressed" Value="true"> <Setter TargetName="MaskOnPressed" Property="Visibility" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button>
画面側のXAML
ボタンを画面に貼っつけたXAML、こちらもコードビハインドなし。
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Canvas> <local:CustomButton Canvas.Left="10" Canvas.Top="10" Width="100" Height="20" Content="ボタン1" /> <local:CustomButton Canvas.Left="10" Canvas.Top="40" Width="100" Height="20" Content="ボタン2" /> <local:CustomButton Canvas.Left="10" Canvas.Top="70" Width="100" Height="20" Content="ボタン3" IsEnabled="False" /> </Canvas> </Window>
実行時イメージ
上から順に、
フォーカス取得中
フォーカス無しの表示
Disable(IsEnabled=false)の表示
ポイント
標準スタイルの無効化
・OverridesDefaultStyle=”true”で標準のスタイルを読み込まないように
・FocusVisualStyle="{x:Null}"でフォーカス取得時スタイルを初期化
(フォーカス取得時に点線が表示されるやつ。)
トリガーで実現しているもの
・フォーカス時に外枠の色を濃い目に変更
・マウスオーバー時に塗りつぶし色を濃い目に変更
・Disableの時、全体を半透明にして使えないっぽい外観に
・押下時、半透明のフィルタを被せて操作に対するレスポンスを表現
WPF 描画の練習 マル印
前回の記事に引き続き、WPFの描画周りを練習
前回の記事はこちら↓
nomoredeathmarch.hatenablog.com
前回はバツ印を作ったので今回はマル印を作ってみました。
まだ簡単・・・
イメージ
XAML
<UserControl x:Class="WpfApp1.UserControl2" 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:WpfApp1" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Canvas Height="100" Width="100" Background="Aqua" > <Path Stroke="Black" > <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Tomato" Offset="0"/> <GradientStop Color="Red" Offset="0.5"/> <GradientStop Color="Crimson" Offset="0.7"/> </LinearGradientBrush> </Path.Fill> <Path.Data> <CombinedGeometry GeometryCombineMode="Xor" > <CombinedGeometry.Geometry1> <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <EllipseGeometry Center="50,50" RadiusX="30" RadiusY="30"/> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> </Canvas> </UserControl>
ポイント
・半径が違う円を重ねて合成
・GeometryCombineModeはXorでGeometry2の領域を描画しない
ジオメトリの使い方、良いサンプルないかなぁってネットで検索したりしてたのですが、
手元にあるエッセンシャルWPFの204ページ辺りにしっかり書いてありました。
エッセンシャルWPF:Windows Presentation Foundation (Programmer's SELECTION)
- 作者: Chris Anderson,星睦
- 出版社/メーカー: 翔泳社
- 発売日: 2007/10/31
- メディア: 大型本
- 購入: 6人 クリック: 128回
- この商品を含むブログ (32件) を見る
WPF 描画の練習 バツ印
描画処理への理解を深めるため、簡単なマークの作成に挑戦してみました。
大したことしてないのに思った以上に「それっぽく」見えるので面白いです。
イメージ
XAML
<UserControl x:Class="WpfApp1.UserControl1" 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:WpfApp1" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Canvas Height="100" Width="100" Background="Aqua" > <Path Stroke="Black" > <Path.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Tomato" Offset="0"/> <GradientStop Color="Red" Offset="0.5"/> <GradientStop Color="Crimson" Offset="0.7"/> </LinearGradientBrush> </Path.Fill> <Path.Data> <CombinedGeometry GeometryCombineMode="Union" > <CombinedGeometry.Geometry1> <RectangleGeometry Rect="0,40,100,20"> <RectangleGeometry.Transform> <RotateTransform CenterX="50" CenterY="50" Angle="45"/> </RectangleGeometry.Transform> </RectangleGeometry> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <RectangleGeometry Rect="0,40,100,20" > <RectangleGeometry.Transform> <RotateTransform CenterX="50" CenterY="50" Angle="135"/> </RectangleGeometry.Transform> </RectangleGeometry> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> </Canvas> </UserControl>
ポイント
・CombinedGeometryで同じ大きさの二つの長方形を合成
・GeometryCombineModeはUnionで双方の領域を描画
・RenderTransformを使って長方形を45度、135度回転
・回転の中心はキャンバスの中心
WPF PathFigureによる描画
直線 - LineSegment
指定座標までの直線を引く。
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <UniformGrid> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <LineSegment Point="100,50"/> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="50,0"> <LineSegment Point="50,100"/> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,0"> <LineSegment Point="100,100"/> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,100"> <LineSegment Point="100,0"/> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,0"> <LineSegment Point="100,25"/> <LineSegment Point="0,50"/> <LineSegment Point="100,75"/> <LineSegment Point="0,100"/> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> </UniformGrid> </Window>
円弧 - ArcSegment
終点、X軸Y軸の半径、時計周りか半時計周りか
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <UniformGrid> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <ArcSegment Point="100,50" Size="1,1" SweepDirection="Clockwise" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <ArcSegment Point="100,50" Size="1,1" SweepDirection="Counterclockwise" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <ArcSegment Point="100,50" Size="1,0.5" IsLargeArc="False" SweepDirection="Clockwise" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,0"> <ArcSegment Point="0,100" Size="1,0.5" IsLargeArc="False" SweepDirection="Clockwise" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="100,0"> <ArcSegment Point="100,100" Size="1,0.5" IsLargeArc="False" SweepDirection="Counterclockwise" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> </UniformGrid> </Window>
2次ペジェ曲線 - QuadraticBezierSegment
Point1は制御点、Point2が終点
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <UniformGrid> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="50,0" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="25,0" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="75,0" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="50,-50" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="25,-50" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <QuadraticBezierSegment Point1="75,-50" Point2="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> </UniformGrid> </Window>
3次ペジェ曲線 - BezierSegment
Point1、Point2が制御点、Point3が終点
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <UniformGrid> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="0,0" Point2="100,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="20,0" Point2="80,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="30,0" Point2="70,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="40,0" Point2="60,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="50,0" Point2="50,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> <Canvas Width="100" Height="100" Background="Aqua"> <Path Stroke="Black"> <Path.Data> <PathGeometry> <PathFigure StartPoint="0,50"> <BezierSegment Point1="100,0" Point2="0,0" Point3="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Canvas> </UniformGrid> </Window>