ちょっとコードが断片的なので問題の特定はできてないですが、
サンプルとして以下の様に書くと単方向バインディングは可能です。
for文内の Bindingのコードは提示されたコードに合わせています。
WPFアプリケーションを作成
WindowにLabelを二つ置き、NameをLabel0, Label1とする。
WindowのLoadイベントを作成し、コードを以下のようにする。
※ Window_LoadedとMyModelクラスの定義をしただけです。
cs
1 public partial class MainWindow : Window {
2 public MainWindow ( ) {
3 InitializeComponent ( ) ;
4 }
5
6 private void Window_Loaded ( object sender , RoutedEventArgs e ) {
7
8 List < Label > labelns = new List < Label > { Label0 , Label1 } ;
9 for ( var i = 0 ; i < labelns . Count ; i ++ ) {
10 var iKoumokuNo = i ;
11 var iLabelNo = i ;
12 Binding textNamebinding = new Binding ( ) ;
13 string name = "ListName" + ( iKoumokuNo ) . ToString ( ) ;
14 textNamebinding . Path = new PropertyPath ( name ) ;
15 BindingOperations . SetBinding ( labelns [ iLabelNo ] , Label . ContentProperty , textNamebinding ) ;
16 }
17
18 this . DataContext = new MyModel ( ) ;
19 }
20
21 public class MyModel {
22 private string value = "Hello 0" ;
23
24 public string ListName0 {
25 get { return value ; }
26 set { this . value = value ; }
27 }
28
29 public string ListName1 {
30 get { return value ; }
31 set { this . value = value ; }
32 }
33 }
34 }
質問でわからなかったのは
「最終的にINotifyPropertyChanged を継承したクラス」と最初のコード「private string listName0;」のクラス構成
「listName[]配列」 とはなにか(その配列をどう宣言したのか)
ちなみに、簡単にINotifyPropertyChangedを実装してみました。
Windowsにはボタンを1つ追加する必要があります。
MyModelをnewするタイミングも変わっています。
var h = PropertyChangedHandler;
は、var h = PropertyChanged;
と変わっています。(
そのイベントに誰かが設定しているか判断するものなので)
Bind時に textNamebinding.UpdateSourceTrigger
の指定が増えている事にも注意してください。
SetPropertyは簡単のためにジェネリックメソッドではなくしました。
cs
1 public partial class MainWindow : Window {
2 public MainWindow ( ) {
3 InitializeComponent ( ) ;
4 }
5
6 private MyModel vm = new MyModel ( ) ;
7
8 private void Window_Loaded ( object sender , RoutedEventArgs e ) {
9
10 List < Label > labelns = new List < Label > { Label0 , Label1 } ;
11 for ( var i = 0 ; i < labelns . Count ; i ++ ) {
12 Binding textNamebinding = new Binding ( ) ;
13 var iKoumokuNo = i ;
14 var iLabelNo = i ;
15 string name = "ListName" + ( iKoumokuNo ) . ToString ( ) ;
16 textNamebinding . Path = new PropertyPath ( name ) ;
17 textNamebinding . UpdateSourceTrigger = UpdateSourceTrigger . PropertyChanged ;
18 BindingOperations . SetBinding ( labelns [ iLabelNo ] , Label . ContentProperty , textNamebinding ) ;
19 }
20
21 this . DataContext = vm ;
22 }
23
24 private void Button_Click ( object sender , RoutedEventArgs e ) {
25 vm . ListName0 = "a" ;
26 vm . ListName1 = "b" ;
27 }
28
29
30 public class MyModel : INotifyPropertyChanged {
31 private string listName0 = "Hello 0" ;
32 private string listName1 = "Hello 1" ;
33
34 public string ListName0 {
35 get { return listName0 ; }
36 set { SetProperty ( ref listName0 , value , "ListName0" ) ; }
37 }
38
39 public string ListName1 {
40 get { return listName1 ; }
41 set { SetProperty ( ref listName1 , value , "ListName1" ) ; }
42 }
43
44 public virtual bool SetProperty ( ref String target , String value , string name ) {
45 if ( target == null ) {
46 if ( value == null )
47 return false ;
48 }
49 else {
50 if ( target . Equals ( value ) )
51 return false ;
52 }
53 target = value ;
54 RaisePropertyChanged ( name ) ;
55 return true ;
56 }
57
58 protected virtual void RaisePropertyChanged ( string name ) {
59 var h = PropertyChanged ;
60 if ( h != null )
61 h ( this , new PropertyChangedEventArgs ( name ) ) ;
62 }
63
64 public event PropertyChangedEventHandler PropertyChanged ;
65 }
追記
上記のListName0 と ListName1 を別個のプロパティではなく、配列 ListName[] として持たせたいということですね。
この場合、ListNameのsetterの処理によってRaisePropertyChangedが呼ばれても、そもそも 配列ListNameをまるごと更新することはないので、そのsetterは使わることがなく、RaisePropertyChangedが発行されることはありません。
(MainWindowの変更は省略。Bindingに設定するnameは "ListName[" + iKoumokuNo + "]";
にすれば良い)
cs
1 private string [ ] listName = { "Hello 0" , "Hello 1" } ;
2 public string [ ] ListName {
3 get { return listName ; }
4 set { SetProperty ( ref listName , value , "ListName" ) ; }
5 }
このセッターは要素への代入では呼ばれない。
cs
1 private void Button_Click ( object sender , RoutedEventArgs e ) {
2 vm . ListName [ 0 ] = "a" ; // これではListNameのセッターは呼ばれない
一番単純な解決策は、要素へのSetメソッドを用意してPropertyChangedを呼ぶことです。
MyModel
public void SetListName(int index, string value) {
listName[index] = value;
var h = PropertyChanged;
if (h != null)
h(this, new PropertyChangedEventArgs("ListName"));
}
MainWindow#Button_Click
private void Button_Click(object sender, RoutedEventArgs e) {
vm.SetListName(0, "a");
vm.SetListName(1, "b");
}
ただ使い方が変わるので扱いにくいですね。
WPFには System.Collections.ObjectModel.ObservableCollection<T>
があるのでこれを利用することができます。
cs
1 // using System.Collections.ObjectModel; を追加する。
2 public partial class MainWindow : Window {
3 public MainWindow ( ) {
4 InitializeComponent ( ) ;
5 }
6
7 private MyModel vm = new MyModel ( ) ;
8 private void Window_Loaded ( object sender , RoutedEventArgs e ) {
9
10 List < Label > labelns = new List < Label > { Label0 , Label1 } ;
11 for ( var i = 0 ; i < labelns . Count ; i ++ ) {
12 Binding textNamebinding = new Binding ( ) ;
13 var iKoumokuNo = i ; var iLabelNo = i ;
14 string name = "ListName[" + iKoumokuNo + "]" ;
15 textNamebinding . Path = new PropertyPath ( name ) ;
16 textNamebinding . UpdateSourceTrigger = UpdateSourceTrigger . PropertyChanged ;
17 BindingOperations . SetBinding ( labelns [ iLabelNo ] , Label . ContentProperty , textNamebinding ) ;
18 }
19
20 this . DataContext = vm ;
21 }
22
23 private void Button_Click ( object sender , RoutedEventArgs e ) {
24 vm . ListName [ 0 ] = "a" ;
25 vm . ListName [ 1 ] = "b" ;
26 }
27
28
29 public class MyModel : INotifyPropertyChanged {
30 private ObservableCollection < string > listName = new ObservableCollection < string > ( ) ;
31
32 public MyModel ( ) {
33 listName . Add ( "Hello 0" ) ;
34 listName . Add ( "Hello 1" ) ;
35
36 listName . CollectionChanged += listName_CollectionChanged ;
37 }
38
39
40 public ObservableCollection < string > ListName {
41 get {
42 return listName ;
43 }
44 set {
45 SetProperty ( ref listName , value , "ListName" ) ;
46 }
47 }
48
49 void listName_CollectionChanged ( object sender , System . Collections . Specialized . NotifyCollectionChangedEventArgs e ) {
50 // 項目の変更やリスト全体の変更時に発生するイベント
51 var h = PropertyChanged ;
52 if ( h != null )
53 h ( this , new PropertyChangedEventArgs ( "ListName" ) ) ;
54
55 }
56
57 public virtual bool SetProperty ( ref ObservableCollection < string > target , ObservableCollection < string > value , string name ) {
58 // サンプルでは使ってないのでnullチェック省略省略
59 target = value ;
60 RaisePropertyChanged ( name ) ;
61 return true ;
62 }
63
64 protected virtual void RaisePropertyChanged ( string name ) {
65 var h = PropertyChanged ;
66 if ( h != null )
67 h ( this , new PropertyChangedEventArgs ( name ) ) ;
68 }
69
70 public event PropertyChangedEventHandler PropertyChanged ;
71 }
72 }
もっと良いやり方もあるかもしれませんが、これで目的は達成できるかと思います。