メイン画面にListViewを配置し、ItemsTemplateにListBoxを設定している。
ListViewには ObservableCollection<ListBoxViewModel>をバインドしている。
コメj理宇市ListBoxViewModelクラスは独自に作成したListBoxにバインドするためのViewModel
この状態で、ListBoxの項目を上下に移動させた場合に、移動させた項目の選択状態がなくなってしまうので、連続で上下に移動させることができない。
<上下移動させたときの処理>
int i = cardlist.Cards.IndexOf(card);
if (i == 0) { break; }
model.Card c = cardlist.Cards[i - 1];
cardlist.Cards.Remove(card);
cardlist.Cards.Insert(i-1, card);
cardlist.SetSelectedIndex(i - 1);
そのため、ListViewから自動生成されたListBoxを取得し、SelectedIndexを再設定する方法を調べたところ、VisualTreeHelperを利用した素敵なメソッドを作られた方がいたので、なんとか実装できた。
(https://blog.xin9le.net/entry/2013/10/29/222336)
※クラス名を「DependencyObjectExtensions」から「VisualTreeHelperExtention」へ変更して利用している
始めはViewModelからViewを取得して、そこからコントロールを辿って・・・ということを考えていろいろと調べていたが、ViewModelからViewを取得するのはなかなかめんどくさそうだった。そもそもそんな必要なかったんだけど・・・。
viewModel.CardLists・・・ListViewにバインドしているObservableCollection<ListBoxViewModel>
ListBoxViewModel・・・ListBoxにバインドしているViewModelObservableCollection<CustomListBoxItem>
foreach (var cardlist in viewModel.CardLists)
{
if (cardlist.Cards.Contains(card)) {
// 入れ替え
int i = cardlist.Cards.IndexOf(card);
if (i == 0) { break; }
model.Card c = cardlist.Cards[i - 1];
cardlist.Cards.Remove(card);
cardlist.Cards.Insert(i-1, card);
cardlist.SetSelectedIndex(i - 1);
// ListViewからVisualTreeHerlerを利用してCardListコントロールを取得し、SelectedIndexを設定する
var controlCardLists = VisualTreeHelperExtention.Descendants<controls.CardList>(lstMainCardList);
foreach (var ctlCardList in controlCardLists)
{
if (ctlCardList.GetBindingViewModel() == cardlist) {
ctlCardList.GetMainList().SelectedIndex = ctlCardList.GetMainList().Items.IndexOf(card); break;
}
}
};
}
IValueConverterについて
IValueConverterについて、文字列をバインドしてIValueConverterで色に変換したものをバインドすることがあったのでメモ。
図のように色を変更するような場合に利用する。
色の情報は文字列や数値として保持し、バインドするときにSolidColorBrushに変換してからバインドするような場合に利用する。
CardBackgroundConverter.cs
public class CardBackgroundConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string colorCode = (string)value;
SolidColorBrush color =null;
if(colorCode == "") { return null; }
var alpha = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(1, 2), 16));
var red = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(3, 2), 16));
var green = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(5, 2), 16));
var blue = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(7, 2), 16));
color = new SolidColorBrush(Color.FromArgb(alpha, red, green, blue));
return color;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
使い方(一部抜粋)
<UserControl x:Class="TaskManager.controls.Card"
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:TaskManager.controls"
xmlns:converter="clr-namespace:TaskManager.converter"
mc:Ignorable="d"
Height="Auto" Width="250">
<UserControl.Resources>
<converter:CardBackgroundConverter x:Key="BackgroundConverter"/>
</UserControl.Resources>
<DockPanel Background="{Binding ColorCode,Converter={StaticResource BackgroundConverter}}"/>
</UserControl>
仕様変更などで色の種類が増えた場合にも、文字色の選択肢を増やすだけで対応が可能。
色以外にもVisibilityなどもIValueConverterで変換できる。
例)ある選択肢の値が1,2,5の時は別のコントロールを非表示。それ以外は表示など
正直慣れないうちは何をしているのかよくわからない。
慣れてくると段々、見るポイントが分かってくる。
デザイナをみてバインド時にValueConverterを指定していれば何の値(バインドされているプロパティの値)がそのコントロールの何のプロパティを変更しているかわかる、気がする。
図のように色を変更するような場合に利用する。
色の情報は文字列や数値として保持し、バインドするときにSolidColorBrushに変換してからバインドするような場合に利用する。
CardBackgroundConverter.cs
public class CardBackgroundConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string colorCode = (string)value;
SolidColorBrush color =null;
if(colorCode == "") { return null; }
var alpha = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(1, 2), 16));
var red = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(3, 2), 16));
var green = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(5, 2), 16));
var blue = System.Convert.ToByte(System.Convert.ToInt32(colorCode.Substring(7, 2), 16));
color = new SolidColorBrush(Color.FromArgb(alpha, red, green, blue));
return color;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
使い方(一部抜粋)
<UserControl x:Class="TaskManager.controls.Card"
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:TaskManager.controls"
xmlns:converter="clr-namespace:TaskManager.converter"
mc:Ignorable="d"
Height="Auto" Width="250">
<UserControl.Resources>
<converter:CardBackgroundConverter x:Key="BackgroundConverter"/>
</UserControl.Resources>
<DockPanel Background="{Binding ColorCode,Converter={StaticResource BackgroundConverter}}"/>
</UserControl>
仕様変更などで色の種類が増えた場合にも、文字色の選択肢を増やすだけで対応が可能。
色以外にもVisibilityなどもIValueConverterで変換できる。
例)ある選択肢の値が1,2,5の時は別のコントロールを非表示。それ以外は表示など
正直慣れないうちは何をしているのかよくわからない。
慣れてくると段々、見るポイントが分かってくる。
デザイナをみてバインド時にValueConverterを指定していれば何の値(バインドされているプロパティの値)がそのコントロールの何のプロパティを変更しているかわかる、気がする。
登録:
投稿 (Atom)
PowerShellでEdgeを自動化(インストール不要。参考:郵便追跡サービス自動操作)
1.経緯について RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。 ※いざというときの手札として持っているだけで安心感が段違い 見た目上IEがインストールされていなくても、CreateObject...
-
TreeListView上でコンボボックスを利用するときにフォーカスのあるコンボボックスの色をイベントで変えようとしたけど上手くいかなかった。 色々と調べているとXaml側のテンプレートをいじる必要があるみたいだったので、いろいろとやってみた。 とりあえず、コンボボックス...
-
サイトに自動でログインするVBSのソース 事前に対象のWebサイトを開いて、F12キーを押下して、要素の名前を調べておく。 ※Edge、Chromeなどのブラウザ objIE.Visible = Trueの部分を objIE.Visible = Falseにしておけば...
-
開発中のプログラムがあまり進んでないのでSQLの小ネタ。 昔、よくあった遅いSQLの改善方法について、記載。 インデックスを張ったりするのもいいけど、SQLを作るときにデータをたくさん持ってきてまとめて条件分岐をCASE式でするだけで 圧倒的に速度が改善できる。 例えば...