nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

簡単なWPFアプリケーションを作成しましょう (株価を取得するアプリ) [C#][WPF]

はじめに

簡単なWPFサンプルアプリケーションを作成します。 本サンプルでは、Html Agility Packというライブラリを使用するため、あらかじめプロジェクトにインストールしてください。 方法は以下のページにあります。 www.atmarkit.co.jp

プロジェクト名は任意でかまいません。本アプリでは、WpfApp4となっております。 本アプリは、Visual Studio Community 2017で作成されています。

株価取得アプリ例

テキストボックスとボタンがひとつだけの簡単なアプリです。 テキストボックスに株価コードを入力すると、アプリが、https://finance.yahoo.co.jp/の該当する企業のページから株価を取得して、メッセージダイアログに表示します。

f:id:nprogram:20180103160052p:plain

なお、検索ボタンを押すと、メッセージダイアログを表示するまで、検索ボタンは無効になります。

f:id:nprogram:20180103160705p:plain

コード

編集するのは、MainWindow.xamlMainWindows.xaml.csのみです。

<Window x:Class="WpfApp4.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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="検索" HorizontalAlignment="Left" Margin="65,72,0,0" VerticalAlignment="Top" Width="253" Click="Button_Click" IsEnabled="{Binding CanPushSearchButton, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Name="TextBox1" Text="{Binding SecurityCode, Mode =TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="65,39,0,0" VerticalAlignment="Top" Width="253">
        </TextBox>
        <Label Content="株価コードを入力してください" HorizontalAlignment="Left" Height="24" Margin="72,10,0,0" VerticalAlignment="Top" Width="246"/>
    </Grid>
</Window>
using System;
using System.Text;
using System.Windows;
using System.Net.Http;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApp4
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {

        public string SecurityCode { get; set; } = "";

        private bool canPushSearchButton = true;
        public bool CanPushSearchButton
        {
            get { return this.canPushSearchButton; }
            set { this.SetProperty(ref this.canPushSearchButton, value); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null)
        {
            if (Equals(field, value)) { return false; }
            field = value;
            var h = this.PropertyChanged;
            if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); }
            return true;
        }

        // コンストラクタ
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = this;
        }

        // 検索ボタンを押したときの処理
        private async void Button_Click(object sender, RoutedEventArgs e)
        {

            if (String.IsNullOrEmpty(this.SecurityCode))
            {
                MessageBox.Show("テキストボックスに証券コードを入力してください。");
                return;
            }

            this.CanPushSearchButton = false;

            // 株価コード文字列を生成する (例 : 7984.T)
            string code = this.SecurityCode + ".T";

            // 株価を取得したいサイトのURLを生成する
            var urlstring = string.Format("http://stocks.finance.yahoo.co.jp/stocks/detail/?code={0}", code);

            // 指定したサイトのHTMLをストリームで取得する
            var doc = new HtmlAgilityPack.HtmlDocument();
            using (var client = new HttpClient())
            using (var stream = await client.GetStreamAsync(new Uri(urlstring)))
            {
                // HtmlAgilityPack.HtmlDocumentオブジェクトにHTMLを読み込ませる
                doc.Load(stream, Encoding.UTF8);
            }

            // XPathを指定し株価部分を取得する
            var nameNode = doc.DocumentNode.SelectSingleNode("//*[@id=\"main\"]/div[5]/div[1]/div[2]/table/tr/th/h1");

            // XPathを指定し株価部分を取得する
            var priceNode = doc.DocumentNode.SelectSingleNode("//*[@id=\"main\"]/div[5]/div[1]/div[2]/table/tr/td[2]");

            if (nameNode == null || priceNode == null)
            {
                MessageBox.Show("証券コードの株価を正しく取得できませんでした。");
                this.CanPushSearchButton = true;
                return;
            }

            // メッセージボックスで表示する
            MessageBox.Show(nameNode.InnerText + "の株価:" + priceNode.InnerText + "円");

            this.CanPushSearchButton = true;
        }
    }
}

参考ページ

今後の改善点

  • 企業の株価しか表示できないのは不便ですので、その他の情報も表示できるようにしたい
  • 複数の企業の情報を表示できるようにしたい
  • MVVMで作成されたアプリにしたい

余力があれば

  • AngleSharpを使って、簡単にスクレイピングしたい qiita.com