TreeView関連のデータ各種処理
TreeViewにデーターを入れる
using System;
using Gtk;
using UI = Gtk.Builder.ObjectAttribute;
private Gtk.ListStore testStore;
private void _mkData(){
testModel testModel1 = new testModel();
testModel1.aId = 1;
testModel1.testStr = "aaaaa";
testStore = new Gtk.ListStore (typeof (testModel));
testStore.AppendValues (testModel);
treeView1.Model = testStore;
}
public class testModel
{
public long aId { get; set; }
public string testStr { get; set; }
}
TreeViewの表示の仕方について詳しく書いてあります。
データストアのデータを取り出す
データストアにインサートしたデータをForeachで取り出せます。
private Gtk.ListStore testStore;
testStore.Foreach (delegate (ITreeModel model, TreePath path, TreeIter iter) {
testModel testModel1 = model.GetValue(iter, 0) as testModel;
return false;
});
static public List<T> _getData<T>(this Gtk.ListStore listStore)
{
List<T> objectArray = new List<T>();
listStore.Foreach((model, path, iter) =>{
T object1 = (T)model.GetValue(iter, 0);
objectArray.Add(object1);
return false;
});
return objectArray;
}
CombBoxの選択したデータを取り出す
private void on_comboBox1_changed(object sender , EventArgs e){
TreeIter tree;
comboBox1.GetActiveIter(out tree);
testModel testModel1 = (testModel)testStore.GetValue (tree, 0);
}
CombBoxの選択したindexを取得設定する
private void on_comboBox1_changed(object sender , EventArgs e){
int selectedIndex = ((Gtk.ComboBox)sender).Active;
}
comboBox1.Active = 0;
TreeViewのRowを選択しデータを取り出す
AutoConnectした状態にする。
コールバック関数を追加し、GetSelectedを呼び出す
private void on_selection1_Changed(object sender , EventArgs e){
ITreeModel model;
TreeIter iter;
if (treeView1.Selection.GetSelected(out model,out iter))
{
testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
}
}
static public object _getSelectionSelectedRow<T>(this Gtk.TreeView treeView,Gtk.ListStore listStore)
{
TreeIter iter;
ITreeModel model;
if (treeView.Selection.GetSelected(out model,out iter))
{
T modelData = (T)listStore.GetValue(iter, 0);
return modelData;
}
return null;
}
チェックボタンからデータを取り出す
private Gtk.ListStore testStore;
void _mkToggle()
{
Gtk.TreeViewColumn DelColumn = new Gtk.TreeViewColumn ();
Gtk.CellRendererToggle CellRendererToggle = new Gtk.CellRendererToggle();
DelColumn.Title = "削除";
CellRendererToggle.Width = 100;
DelColumn.PackStart(CellRendererToggle, true);
//イベントハンドラ1
CellRendererToggle.Toggled += delegate(object o, ToggledArgs args) {
TreeIter iter;
if(testStore.GetIterFromString(out iter, args.Path)) {
testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
}
};
//イベントハンドラ2
CellRendererToggle.Toggled += new ToggledHandler(testToggled);
}
private void testToggled(object o, ToggledArgs args) {
TreeIter iter;
if(testStore.GetIterFromString(out iter, args.Path)) {
testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
}
}
static public object _getToggledRow<T>(this Gtk.ListStore listStore, ToggledArgs args)
{
TreeIter iter;
if (listStore.GetIterFromString(out iter, args.Path))
{
T modelObj = (T)listStore.GetValue(iter, 0);
return modelObj;
}
return null;
}
TreeViewのCellを編集できるようにする
Gtk.TreeViewColumn artistColumn = new Gtk.TreeViewColumn ();
artistColumn.Title = "Artist";
artistColumn.Expand = true;
artistColumn.Sizing = TreeViewColumnSizing.Autosize;
Gtk.CellRendererText artistCellRendererText = new Gtk.CellRendererText ();
artistCellRendererText.Editable = true;
artistCellRendererText.Edited += new EditedHandler(TextCellEdited);
private void TextCellEdited (object o, EditedArgs args)
{
TreePath treePath1 = new TreePath (args.Path);
TreeIter iter;
testStore.GetIter (out iter, treePath1);
testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
Console.WriteLine(args.NewText);
}
Listoreのイベントからデータを取り出す
listStore1 = new Gtk.ListStore (typeof (testModel));
listStore1.RowChanged += delegate(object o, RowChangedArgs args)
{
ListStore testStore = ((ListStore)o);
TreeIter iter;
if (testStore.GetIter(out iter, args.Path))
{
testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
}
};
Listoreのイベントからデータを取り出すExtension
static public List<T> _getData<T>(this Gtk.ListStore list)
{
List<T> objectArray = new List<T>();
list.Foreach((model, path, iter) =>{
T object1 = (T)model.GetValue(iter, 0);
objectArray.Add(object1);
return false;
});
return objectArray;
}
ListStoreのデータソートDescのやり方
やり方1
先頭に一件だけ追加する。
Gtk.TreeIter iterFirst;
//先頭のIterを取得する
musicListStore.GetIterFirst(out iterFirst);
//先頭の前のIterを取得する
Gtk.TreeIter iter = musicListStore.InsertBefore(iterFirst);
Song Song1 = new Song ("test test", "testtest");
//Liststoreにセットする
musicListStore.SetValue(iter, 0, Song1);
最後の行の後に一件だけ追加する
Gtk.TreeIter iter = musicListStore.Append();
Song Song1 = new Song ("Daft Punk", "Technologic");
musicListStore.SetValue(iter, 0, Song1);
やり方2
Gtk.TreeModelSortを使ったやり方 (動作させるにはひと工夫必要)
modelの値を指定してDescさせるやり方。
TreeModelSortというクラスを使うと順番を変更できる。
//ソート やり方2
//TreeModelSortを使用するやり方
Gtk.TreeModelSort sortable = new Gtk.TreeModelSort(TestListStore);
sortable.SetSortFunc(0, delegate(
ITreeModel model,
TreeIter iter,
TreeIter treeIter){
TestView s1 = (TestView)model.GetValue(iter, 0);
TestView s2 = (TestView)model.GetValue(treeIter, 0);
return DateTime.Compare(s1.Create_date, s2.Create_date);
});
treeView1.Model = sortable;
ソート やり方1について
ListStore.Clearを使う時の注意点
ListStore.Clear実行すると以下のエラーが出ることがる。
ITreeModelに登録されたiterがTreeModelの中で消えていないため?
iterはデータや何行目を元にハッシュにしてパスとして使っている?
データの配列の順番を替えたりすると、treeView1.ModelにListStoreを入れるエラーが出ることがある。
Modelのiterの設定を事前にリセットする
TreeView.ModelとListStoreがつながった状態でListStoreのAppendValuesにデータを入れる瞬間に、TreeViewでトリガーで何か関数が走る。iterの設定がおかしいとここでエラーがでる。
Modelにnullを入れることでModelの中のiterの設定をリセットしておく
Gtk-CRITICAL **: gtk_list_store_iter_next: assertion
'priv->stamp == iter->stamp' failed
Gtk-CRITICAL **: gtk_tree_path_to_string: assertion
'path != NULL' failed
Gtk-CRITICAL **: gtk_list_store_get_value: assertion
'iter_is_valid (iter, list_store)' failed
ポイント
Nullを入れてやる。その後ListStorをClearする
treeView1.Model = null;
ListStore.Clear();
OK
gtk_tree_path_to_string系のエラーはModelにnullを入れたら消えた。
Gtk-CRITICAL **:gtk_tree_path_to_string: assertion 'path != NULL' failed
treeView1.Model = null;
データーをがちゃがちゃいじりすぎるとClear時にエラーが起きます。
データーは一件ずつ先頭や最後に入れていくのがよいです。
Clearの後にはModelにnullを入れておいたほうがよい。
追記
UIの更新で注意点
Webなどの非同期処理の中で一緒にUIを更新するとクラッシュすることがありました。
UIの更新は同期のしたほうが安定していて確実です。