CustomScript

ページ

ラベル WPF の投稿を表示しています。 すべての投稿を表示
ラベル WPF の投稿を表示しています。 すべての投稿を表示

2018年6月1日金曜日

WPF勉強(13) Edge版WebViewコントロールを使ってみる

  • Windows10 April 2018 Update
  • .Net Frameork 4.6.2
  • WPF
  • VisualStudio2017
Windows Community Toolkit 3.0 で Edge版のWebViewコントロールが使用できるようになりましたので、早速使ってみます。

WebView controls for Windows Forms and WPF applications

動作環境


  • Windows 10 April 2018 Update 以上
  • .Net Framework 4.6.2 以上

準備


Nuget で Microsoft.Toolkit.Wpf.UI.Controls.WebView を導入

実装



  • 名前空間の定義を追加(7行目)
  • WebViewコントロールを配置(11行目)
簡単ですね。

おまけ:表示中のhtmlテキストを取得する


DOMContentLoadedイベントで読み込み完了を検知できるのでその後の適当なタイミングで。



(2019-02-04) Nugetパッケージを最新のものに変更

2016年4月18日月曜日

VisualStudio 2015 Update2 のメモ

  • VisualStudio2015
  • WPF
  • C#
久々に技術ネタを投稿。

VisualStudio 2015 Update2 がきていました。
詳細はこちら。

Visual Studio 2015 Update 2
https://www.visualstudio.com/news/vs2015-update2-vs

Visual Studio 2015 Update 2 リリース
https://blogs.msdn.microsoft.com/visualstudio_jpn/2016/03/31/visual-studio-2015-update-2-rtm/

C/C++パフォーマンスが改善されてたり、Git LFS対応とかいろいろありますが、その中で自分に関係しそうなWPFとC#に関連する変更点のみ挙げてみます。


C#インタプリタ


C#インタプリタを気軽に試せるようになりました。
「対話形式で実行(Ctrl+E,Ctrl+E)」 で C#インタラクティブウィンドウが開きます。
手前に開かないのでわかりにくいですが、ドキュメントのタブに[C# Interactive]が増えてると思います。
コンソールになっているので、以下のようにC#命令を直接入力実行できます。

> Console.WriteLine("Hello!")
Hello!

ソースコードのコードを選択してからCtrl+E,Ctrl+Eすると、そのコードをC#インタラクティブウィンドウ上で実行できるので、ちょっとしたチェックに使用できる、かな?

「#help」 で操作方法が表示されますが、それを見るとdllの読み込みやスクリプトの実行ができるようです。

・・といった感じですが、有用な活用方法が私には今のところなさげです。


コード修正機能がより便利になった -- Typo修正


コード上に現れる電球マークを押すとusing宣言を挿入したりインターフェイスの雛形を挿入してくれる便利な機能があるのですが、多少打ち間違えた場合でも正しいクラス名とかに修正してくれるようになりました。

例えば、
Straem
のようなtypoを
Stream
になおしてくれる、といった感じです。

試してみたのですが、修正が効かない場合があったり期待とは異なる修正を提案したりするので、過剰な期待はしないほうが良いでしょう。

ちなみに例で上げたようなtypoは Ctrl+t で前後の文字入れ替えるという機能を使って修正することができます。

コード修正機能がより便利になった -- null条件演算子へ変換、等


これもコード修正機能です。
if (action != null) action();
といったコードを
action?.Invoke();
のようなnull条件演算子を使用した修正を提案するようになりました。

他にも、awaitを使用してないasync関数からasyncを削除する修正を提案したりするようです。


C#アナライザのパフォーマンス向上


C# Analyzer および Visual Basic Analyzer の API が改良され、生成されたコードでアナライザーを実行するときのパフォーマンスと制御性が向上した、ようです。

使ってないのでよくわからないっす。


アプリ内のUIデバッグメニュー


WPFのプロジェクトをデバッグ実行すればすぐわかると思うのですが、アプリのタイトルバー直下にXAMLデバッグ用のUIメニューが表示されるようになりました。今までライブビジュアルツリーにあった機能ですが、それがより使いやすくなった感じでしょうか。


これを表示したくない場合は、[デバッグ(D)]>[オプション(O)] で「デバッグ>全般」の「アプリケーションでランタイムツールを表示」のチェックを外します。

あと、XAMLデバッグ関係ではライブプロパティエディタにアクセシビリティプロパティ(AutomationPeer)が表示されるようになったようです。うん、よくわからん。

これらのXAMLデバッグ機能については以下の動画(英語)を見るとなんとなくわかります。

Runtime Editing Tools for XAML
https://www.youtube.com/watch?v=Ama_giXPtvE



このムービーでは実行中にXAML編集していますが、これはUpdate2ではなく次期VisualStudioの新機能(現在プレビュー版)です

2015年12月21日月曜日

WPF勉強(12) ComboBoxとEnum

  • WPF
  • .NET 4.5
  • C# 6.0
enumをComboBoxで使う方法です。
2パターンの実装サンプルを紹介します。

Enum名で選択する

ComboBox で選択させるためにはとにかく選択項目のリストが必要です。
Enum.GetValues() で Enum のリストを作成し、それを ItemSource としてバインドします。

対応する文字列で選択する

Enumと文字列がペアになったリストを使います。今回は Dictionary 型を使用した例になります。
Dictionary を作成し、それを ItemSource としてバインドします。 SelectedValuePath で選択されるプロパティ名、 DisplayMemberPath で表示するプロパティ名を指定します。 今回の場合は Dictionary 型なので "Key" と "Value" になります。

サンプルコード


2014年12月1日月曜日

WPF勉強(9) RichTextBoxの内容をテキストで保存する

  • .Net4.5
 特殊な内部構造のRichTextBoxですが、これをテキスト形式で保存するには次のようにします。
using (var fileStream = System.IO.File.Open(filename, System.IO.FileMode.Create))
{
    TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
    textRange.Save(fileStream, DataFormats.Text);
}

TextRangeすごい。
ちなみに、string形式が欲しい場合はTextプロパティを使います。
string text = textRange.Text;


参考URL
http://stackoverflow.com/questions/4010314/wpf-richtextbox-save-load-in-custom-format

WPF勉強(8) ウィンドウの右下をつまんでリサイズ

  • .Net4.5


ウィンドウ右下を摘むとウィンドウサイズを変えることができるアレを実装します。

WindowコントロールのResizeModeプロパティを CanResizeWithGrip に変更するだけです。簡単。


2014年11月30日日曜日

WPF勉強(7) VisualStudio2013みたいなスタイルのウィンドウを作る

  • .Net4.5
  • Win7


ウィンドウの見栄えをVisualStudio2013のようにします。

下記ページを参考に作成していますので、まずこちらをご一読ください

【grabacr.nét】WPF で Zune のようなウィンドウを作る
 http://grabacr.net/archives/480

使用するリソースは以下の2つです
WindowChrome
非クライアント領域のカスタマイズ
.Net4.5には標準で入っています

PresentationFramework.AeroLite
Windows8っぽいテーマ
参照に追加します。配布バイナリが動かない場合はプロパティの「ローカルコピー」をTrueにしてください

スタイル定義は以下の通りです。
AeroLiteテーマを適用し、システムボタン用にスタイルを幾つか追加定義しています。
<ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <ResourceDictionary.MergedDictionaries>

        <!-- Theme: AeroLite -->
        <ResourceDictionary Source="/presentationframework.AeroLite;component/themes/aerolite.normalcolor.xaml" />

        <!-- Custom Styles -->
        <ResourceDictionary>
            <SolidColorBrush x:Key="WindowColor" Color="#FFD6DBE9"/>
            <SolidColorBrush x:Key="ClientColor" Color="#FF293955"/>

            <!-- System Buttons -->
            <Style x:Key="SystemButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
                <Setter Property="Background" Value="{StaticResource WindowColor}" />
                <Setter Property="BorderBrush" Value="{StaticResource WindowColor}" />
                <Setter Property="IsTabStop" Value="False"/>
                <Setter Property="FontFamily" Value="Marlett" />
                <Setter Property="FontSize" Value="14px" />
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Padding" Value="12,8,10,4" />
            </Style>

            <!-- ウィンドウ最大化時に枠幅を変更するためのスタイル-->
            <Style x:Key="MaximumStyle" TargetType="Grid">
                <Setter Property="Background" Value="{StaticResource WindowColor}"/>
                <Setter Property="Margin" Value="6"/>
            </Style>
            <Style x:Key="NormalStyle" TargetType="Grid">
                <Setter Property="Background" Value="{StaticResource WindowColor}"/>
                <Setter Property="Margin" Value="0"/>
            </Style>
            
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

ウィンドウ定義は以下通りです。
標準ボタンの代わりになるコントロールをごりごり書いています。
<Window x:Name="SampleWindow" x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SampleApplication" Height="240" Width="360" Background="#FF8F99A0" SnapsToDevicePixels="True" MinWidth="256" MinHeight="128" StateChanged="SampleWindow_StateChanged">

    <WindowChrome.WindowChrome>
        <WindowChrome UseAeroCaptionButtons="False" CaptionHeight="24" ResizeBorderThickness="8" />
    </WindowChrome.WindowChrome>

    <Window.Resources>
        <ResourceDictionary Source="SampleStyle.xaml" />
    </Window.Resources>

    <Border BorderBrush="Black" BorderThickness="1">
        <Grid x:Name="BaseGrid" Style="{StaticResource NormalStyle}">

            <!-- タイトルバー領域 -->
            <Image x:Name="WindowIcon" Margin="4,4,0,0" Source="icon.png" Stretch="Fill" Width="32" Height="32" HorizontalAlignment="Left" VerticalAlignment="Top"/>
            <TextBlock x:Name="WindowTitle" HorizontalAlignment="Left" Margin="44,12,0,0" Text="Sample Application" VerticalAlignment="Top"/>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
                <Button x:Name="MinimizeButton" Content="0" Style="{StaticResource SystemButton}" FontWeight="Bold" Click="MinimizeButton_Click" />
                <Button x:Name="MaximizeButton" Content="1" Style="{StaticResource SystemButton}" Click="MaximizeButton_Click" />
                <Button x:Name="CloseButton" Content="r" Style="{StaticResource SystemButton}" Click="CloseButton_Click" />
            </StackPanel>

            <!-- クライアント領域 -->
            <Grid x:Name="ClientGrid" Margin="0,40,0,0" Background="{StaticResource ClientColor}">
                <Menu Height="24" VerticalAlignment="Top" Background="{StaticResource WindowColor}">
                    <MenuItem Header="ファイル(_C)"/>
                    <MenuItem Header="編集(_E)"/>
                    <MenuItem Header="ヘルプ(_H)"/>
                </Menu>
            </Grid>

        </Grid>
    </Border>
</Window>

ウィンドウのコードは以下の通りです。
コマンドバインドがまだよくわかっていないので、イベントで実装しています。
標準ボタンの置き換えですが、最大化ボタンのみウィンドウの状態で挙動を変化させるようにしています。

最大化時にウィンドウ端のボタン等が見きれてしまうため、コンテンツが画面内に収まるようにスタイルを切り替えてMarginを変えることで対応しています。ですが、正しい方法じゃないよねこれ。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Sample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        // 閉じるボタン
        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            SystemCommands.CloseWindow(this);
        }

        // 最小化ボタン
        private void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            SystemCommands.MinimizeWindow(this);
        }

        // 最大化ボタン
        //ウィンドウ状態によってはウィンドウサイズ復帰動作になる
        private void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
                SystemCommands.RestoreWindow(this);
            else
                SystemCommands.MaximizeWindow(this);
        }

        // ウィンドウ状態が変化したら最大化ボタン記号を変更する
        // 最大化状態になったときに画面外まで表示されるのを防ぐためにスタイルを
        // 変更して画面内にコンテンツが収まるようにする
        private void SampleWindow_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.BaseGrid.Style = (Style)(this.Resources["MaximumStyle"]);
                this.MaximizeButton.Content = "2";
            }
            else
            {
                this.BaseGrid.Style = (Style)(this.Resources["NormalStyle"]);
                this.MaximizeButton.Content = "1";
            }
        }
    }
}
こんなかんじで、それっぽいウィンドウになります。

2014年11月25日火曜日

WPF勉強(4) フォルダ選択ダイアログの作成

  • .Net4.5
簡単に実装するなら FolderBrowserDialog を使えばよいのですが、なんかボタンが小さくてヤダ、WPFなのにFormのコントロールを呼び出しているのがヤダ、というわけで別の方法での実装します。

参照に追加するのは Micorosoft.WindowsAPICodePack と Microsoft.WindowsAPICodePack.Shell です。追加するにはNuGetで「Windows API Code Pack - Shell」をインストールしてください(Coreもインストールされます)。

// Button1 Click Event
private async void Button1_Click(object sender, RoutedEventArgs e)
{
    this.Button1.IsEnabled = false;

    try
    {
        for (int i = 0; i < 10; i++)
        {
            this.TextBox1.AppendText(i + "\n");
#if true
            // 非同期になるし、例外キャッチできる
            await Task.Run(async () => HeavyProcess(i));
            // コンパイラ警告が気になる場合は適当なawaitを追加
            //await Task.Run(async () => {HeavyProcess(i); await Task.Yield();});
#else
            // 非同期になるが、例外キャッチできない
            await Task.Run(() => HeavyProcess(i));
#endif
        }
    }
    catch (Exception ex)
    {
        this.TextBox1.AppendText(ex.Message);
    }

    this.Button1.IsEnabled = true;
}

// Heavy Process
void HeavyProcess(int count)
{
    System.Threading.Thread.Sleep(1000);
    if (count >= 5) throw new ApplicationException("例外発生!!");
}

参考URL
http://stackoverflow.com/questions/4007882/select-folder-dialog-wpf
http://arikalog.hateblo.jp/entry/2013/12/20/211641
 

2014年11月24日月曜日

WPF勉強(3) RichTextBoxで色付きログ表示

  • .Net4.5
ログ表示用のRichTextBoxアクセサクラスを作りました。
通常ログ(Log)はそのまま、エラーログ(LogError)は赤く表示します。

/// <summary>
/// RichTextBoxを色付きログ出力用に拡張
/// </summary>
public class LogTextBox
{
    public RichTextBox RichTextBox { set; get; }

    // コンストラクタ
    public LogTextBox(RichTextBox richTextBox)
    {
        RichTextBox = richTextBox;
    }

    // クリア
    public void Clear()
    {
        var paragraph = RichTextBox.Document.Blocks.LastBlock as Paragraph;
        paragraph.Inlines.Clear();
    }

    // テキスト追加
    public virtual void WriteLine(string text, Brush brush = null)
    {
        var paragraph = RichTextBox.Document.Blocks.LastBlock as Paragraph;

        // 書き込み
        if (brush != null)
        {
            // 色付きでテキスト追加
            var span = new Span { Foreground = brush };
            span.Inlines.Add(text + "\n");
            paragraph.Inlines.Add(span);
        }
        else
        {
            // そのままテキスト追加
            paragraph.Inlines.Add(text + "\n");
        }

        // 最終行にスクロール
        RichTextBox.ScrollToEnd();
    }

    // 通常ログ
    public void Log(object message)
    {
        WriteLine(message.ToString());
    }

    // 警告ログ
    public void LogWarning(object message)
    {
        WriteLine(message.ToString(), Brushes.Orange);
    }

    // エラーログ
    public void LogError(object message)
    {
        WriteLine(message.ToString(), Brushes.Red);
    }
}

RichTextBoxではFlowDocumetで内容が構成されており、その構成は複雑で、ちょっと色を付けるだけでも手間がかかります。

参考URL
http://msdn.microsoft.com/ja-jp/library/aa970779%28v=vs.110%29.aspx
http://noizy-radio.blogspot.jp/2013/02/wpfrichtextbox_22.html
http://blogs.wankuma.com/naka/archive/2008/07/13/148706.aspx

2014年11月23日日曜日

WPF勉強(2) 終了ボタンの実装

  • .Net4.5
[終了]ボタンを押した時にアプリが終わるようにします。

終了ボタンのXAML記述

WPFはxamlでウィンドウの配置等を記述します。これはデザインエディタと連動していて、エディタでグラフィカルに編集しても自動的にxamlに反映されます。

MainWindow.xaml
<window x:Class="CommandWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="560">
    <grid Margin="0,0,0,0">
        <textbox x:Name="TextBoxFolder" Height="23" Margin="10,10,90,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="フォルダを指定"/>
        <button x:Name="ButtonFolder" Content="フォルダ" Margin="0,10,10,0" VerticalAlignment="Top" Click="ButtonFolder_Click" HorizontalAlignment="Right" Width="75"/>
        <richtextbox x:Name="TextBoxLog" Margin="10,38,10,52" VerticalScrollBarVisibility="Visible" IsReadOnly="True">
            <flowdocument>
                <paragraph>
                    <run Text="ここに実行ログを出力"/>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
        <progressbar x:Name="ProgressBarRun" Margin="10,0,10,37" Height="10" VerticalAlignment="Bottom"/>
        <button x:Name="ButtonRun" Content="実行" Margin="0,0,90,8" Click="ButtonRun_Click" Height="24" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75"/>
        <button x:Name="ButtonClose" Content="終了" Margin="0,0,10,8" Click="ButtonClose_Click" Height="24" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75"/>
    </Grid>
</Window>

ほとんどの属性はエディタでぐりぐりやっていれば勝手に設定されるのですが、若干わかりにくい属性について説明します。

x:Name="ButtonClose"

この「名前」は、表示名(Content)ではなく、コードからコントロールにアクセスする変数名になります。

Click="ButtonClose_Click"

ボタンクリックしたときに呼ばれるメソッド名になります。エディタ上でボタンをダブルクリックすると自動で追加されますが、"(x:Name)_Click"というような名前に依存した呼出名になります。名前が定義されていない時は"Button_Click"という呼出名になるようです。


終了ボタンのコード実装

簡単かと思ったのですが、これぞという解説がされている情報を探しだすのに案外手間取りました。判ってしまえば簡単なんですけどね。自身のClose()を呼ぶだけでした。

MainWindow.xaml.csの一部
// アプリ終了
private void ButtonClose_Click(object sender, RoutedEventArgs e)
{
    this.Close();
} 

URL
http://msdn.microsoft.com/ja-jp/library/bb655895%28v=vs.90%29.aspx

WPF勉強(1) なにか作ってみることにした

Visua lStudio Community 2013 でどう勉強しようか、ということでWPFアプリをなにか作ってみることにしました。


機能としては

・フォルダを指定する
・フォルダのすべてのファイルに対してコマンドを実行する

といった感じです。この手の作業はコマンドラインで用足りるのですが、勉強ということでWPFで作ってみます。


で、さっそく新規プロジェクトを作成し、ゴリゴリっとエディタでハリボテWindowを作ってみました。このあたりのツールはFormで作った時と似ていたのでなんとなく出来ました。



ちなみに私のスキルは

・C#:そこそこ
・Windowsプログラム能力:ほんの少し
・.NET:ほんの少し
・WPF:未知の領域

といった感じですが、さて、どうなるでしょう。