株式コードを探すプログラムを考える
C# WPFを使って、ListViewに表示された株価コードと銘柄名のリストをTextBoxに入力したテキストを使って絞り込むプログラムを作成します。
PanRollingチャートギャラリー(体験版を使用しています)で、提供されているCOMモデルでは、株式コードが存在するかどうかを確認するメソッドが提供されていません。データベースに存在しない株式コードを入力するとエラーが発生します。
※ COMモデル関連の情報は、検索エンジンでは、キーワードが、ドメインのcomと競合するため、情報は、かなり探しにくいです。
エラー処理は、コストが高い、つまり、処理が遅くなるため、可能な限り回避するのが基本方針です。理想的には、エラー処理コードと回避処理コードの処理速度を比較検討する必要があるのかもしれません。
株式コードの検索と株式コードが存在するかどうかを確認できるプログラムを作成します。
株式コードの一覧をPanRollingチャートギャラリーで取得する方法は、すでに紹介しています。
実現したい機能は、以下の2つです。
- 取得した株式コードの一覧から、入力したコードが存在するかどうかを確認する
- 完全な株式名称だけでなく、よみがな、略式名称でもコードを検索できるようにする(今回は実装しない)
以前に、PanRollingチャートギャラリー(体験版を使用しています)から、株式コードと銘柄名を取得するプログラムを作成しました。
このとき作成したプログラムで得られた株式コードと銘柄名のリストから、TextBoxに入力した文字で、リストを絞り込むプログラムを作成しようと思います。
ListViewから、項目を絞り込む機能を実装する
実際に使用するモジュールとして機能を追求していくと理解しにくくなります。
コードをどのように実装するかを考えるために、機能を単純に、以下のように変更します。
1つの項目に、2つのデータを持つ、List型のデータの中から、実行時に、TxetBoxに入力した文字が含まれる項目だけ、表示するプログラムを考えます。
C# WPFで、ListViewのリストをTextBoxに入力したテキストで絞り込むプログラム
プログラム全体を考える前に、C# WPFを使って、ListViewに表示されてたリストをTextBoxに入力したテキストを使って絞り込むプログラムを確認します。
ポイント
- データクラスに、IEquatable<T> インターフェイスを実装し、Equalsメソッドを使えるようにする
- TextBoxに入力した文字で、GridViewに表示するリストから、LINQを使って、フィルタリングしたリストを作成する
- 作成したフィルタリングしたリストをつなげて、重複を削除する。
- 最終的なリストをGridViewのItemsSourceに指定する。
Pan Active Market DatabaseをC#で使用するための参照設定
PanRollingチャートギャラリーの体験版は、「 Pan Rolling相場アプリケーション試用版」としてダウンロードできます。
- WPFアプリケーションを作成する
- 参照を追加する
- [プロジェクト] - [参照の追加] - [COM] タブ を選択
- Pan Active Market Database 1.3にチェック
- ActiveMarket という参照が追加される。
使用されている COM DLL は、amarket.dll です。
完成したアプリケーションの実行結果
ListViewのリストをTextBoxに入力したテキストで絞り込む機能を実装する
以前作成した、銘柄と株式コードを取得するC# WPFアプリケーションに、銘柄や株式コードを絞り込む機能を実装します。
IEquatable<T> インターフェイスを実装したデータクラスを作成する
最初に行うのは、株式コードと銘柄名を格納するデータクラスを作成することです。
このプログラムには、TextBoxに入力した文字で、リストをフィルタリングする機能を実装します。TextBoxに入力された文字を使って、株式コードと銘柄名のそれぞれをフィルタリングしたリストを作成し、その2つのリストから、1つの重複のないリストを作成します。
そのため、データクラスには、同じかどうかを確認するためのメソッドが必要です。
データクラス、stock_CodeAndNameは、銘柄名と株式コードに対応するstock_nameとstock_codeの2つのstring型のデータメンバを持っています。
データメンバを複数持つクラスでは、同じかどうかを確認するためのメソッドは、自動で実装してくれないので、自分で実装する必要があります。
クラスのインスタンスが、同じかどうか確認するには、IEquatable
データクラス
stock_CodeAndName.cs
using System;
using System.Collections.ObjectModel;
namespace PanChart_GetStockCode
{
class stock_CodeAndName : IEquatable<stock_CodeAndName>
{
public string stock_name { get; set; } // 銘柄名
public string stock_code { get; set; } // 株式コード
public stock_CodeAndName(string code, string name)
{
stock_code = code;
stock_name = name;
}
public stock_CodeAndName(object code, object name)
{
stock_code = Convert.ToString(code);
stock_name = Convert.ToString(name);
}
// 同じかどうか比較する
public bool Equals(stock_CodeAndName other)
{
if (other == null)
return false;
if (this.stock_code == other.stock_code)
return true;
else
return false;
}
public override bool Equals(Object obj)
{
if (obj == null)
return false;
stock_CodeAndName productObj = obj as stock_CodeAndName;
if (productObj == null)
return false;
else
return Equals(productObj);
}
public override int GetHashCode()
{
// productCodeをint型に変換し、ハッシュコードにします。
if (Int32.TryParse(this.stock_code, out int j))
return j;
else
// 文字列からハッシュコードを生成します。
return this.stock_code.GetHashCode();
}
}
}
ウィンドウのデザインを作成する
ウィンドウのデザインをxamlコードで作成します。
MainWindw.xaml
<Window x:Class="PanChart_GetStockCode.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="株式銘柄リスト" Height="400" Width="350">
<DockPanel>
<Grid DockPanel.Dock="top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Name="stock_code_box"
Height="23" Grid.Column="0"/>
<TextBlock Name="stock_name_box"
Height="23" Grid.Column="1"/>
</Grid>
<TextBox Name="ItemSerch" DockPanel.Dock="Top" TextChanged="ItemSerch_TextChanged" />
<ListView Name="TradingNameList" DockPanel.Dock="Bottom" SelectionChanged="TradingNameList_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="株式コード"
DisplayMemberBinding="{Binding stock_code}" />
<GridViewColumn Header="銘柄名"
DisplayMemberBinding="{Binding stock_name}" />
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</Window>
部分コードを作成します
SetStockDataメソッドで、ListViewのItemsSourceに設定するリストを作成します。リストは、ウィンドウのコンポーネントにデータ結合させたいので、List<T>型ではなく、ObservableCollection<T>型を使用します。
ListViewには、SelectionChangedイベントを設定し、項目を選択すると、TextBlockに表示するコードを記述します。
そして、TextBoxにTextChangedイベントを設定し、文字が入力されると、入力した文字で、ListViewに表示されるリストが、フィルタリングされるように、コードを記述します。
MainWindw.xaml.cs
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace PanChart_GetStockCode
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// ListViewに、ソースを設定する
SetStockData();
}
ObservableCollection<stock_CodeAndName> CodeAndNames = new ObservableCollection<stock_CodeAndName>();
public void SetStockData()
{
ActiveMarket.Names Names = new ActiveMarket.Names();
System.Array codeArray;
System.Array nameArray;
Names.AllNames(ActiveMarket._KindFlag.AM_KINDFLAG_SPOTS, out codeArray, out nameArray);
for (int i = 0; i < codeArray.Length; i++)
{
CodeAndNames.Add(new stock_CodeAndName(codeArray.GetValue(i + 1), nameArray.GetValue(i + 1)));
}
TradingNameList.ItemsSource = CodeAndNames;
}
private void TradingNameList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 項目を選択したとき、それぞれのメンバを表示する
// ListViewで何も選択されていない場合は何もしない
if (TradingNameList.SelectedItem == null) return;
// ListViewで選択されている項目を取り出す
stock_CodeAndName ListItem = (stock_CodeAndName)TradingNameList.SelectedItem;
// ListViewで選択されている項目をテキストボックスに表示する
stock_code_box.Text = ListItem.stock_code;
stock_name_box.Text = ListItem.stock_name;
}
private void ItemSerch_TextChanged(object sender, TextChangedEventArgs e)
{
// 検索ボックスへの入力で、ListViewに表示する内容を変更する
// productCode列の値を入力文字でフィルタリングしたリストを作成する
var filterList_code =
CodeAndNames.Where(x => x.stock_code.Contains(ItemSerch.Text)).ToList();
// productName列の値を入力文字でフィルタリングしたリストを作成する
var filterList_name =
CodeAndNames.Where(x => x.stock_name.Contains(ItemSerch.Text)).ToList();
// 2つのリストを結合して、重複のないリストを作る
var filterList = filterList_code.Union(filterList_name).ToList();
// 作成したリストをItemsSourceに指定する
TradingNameList.ItemsSource = filterList;
}
}
}