Today, I'd like to introduce the problem that we cannot bind "non-INotifyPropertyChanged property" and "INotifyPropertyChanged property" to same ListBox target.
First, I had written property binding like this. I had used "non-INotifyPropertyChanged property".
- The xaml code is here.
<ListBox Height="595" ItemsSource="{Binding}" HorizontalAlignment="Left" Margin="12,6,0,0" Name="listBox1" VerticalAlignment="Top" Width="438"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal"> <TextBlock x:Name="Name1" FontSize="35" Text="{Binding Text1}" Foreground="Black"/> <TextBlock x:Name="Name2" FontSize="35" Text="{Binding Text2}" Foreground="Black"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
- The code behind is here.
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); GetList(); } public void GetList() { List<ItemProperties> items = new List<ItemProperties>(); items.Add(new ItemProperties { Text1 = "test01", Text2 = "test02" }); items.Add(new ItemProperties { Text1 = "test11", Text2 = "test12" }); listBox1.ItemsSource = items; } } public class ItemProperties { private string m_Text1; public string Text1 { get { return m_Text1; } set { m_Text1 = value; } } private string m_Text2; public string Text2 { get { return m_Text2; } set { m_Text2 = value; } } }
Second, I wanted to bind Foreground color in ListBox. So, I added "INotifyPropertyChanged property" as Foreground colors.
The code is like this. But I found I couldn't bind "INotifyPropertyChanged property" to Foreground color in this code.
- The xaml code is here.
<ListBox Height="595" ItemsSource="{Binding}" HorizontalAlignment="Left" Margin="12,6,0,0" Name="listBox1" VerticalAlignment="Top" Width="438"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal"> <TextBlock x:Name="Name1" FontSize="35" Text="{Binding Text1}" Foreground="{Binding Color1}"/> <TextBlock x:Name="Name2" FontSize="35" Text="{Binding Text2}" Foreground="{Binding Color2}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
- The code behind is here.
public partial class MainPage : PhoneApplicationPage { public ObservableCollection<ItemProperties2> ItemCollection { get; private set; } // Constructor public MainPage() { InitializeComponent(); GetList(); GetList2(); } public void GetList() { List<ItemProperties> items = new List<ItemProperties>(); items.Add(new ItemProperties { Text1 = "test01", Text2 = "test02" }); items.Add(new ItemProperties { Text1 = "test11", Text2 = "test12" }); listBox1.ItemsSource = items; } public void GetList2() { ItemCollection = new ObservableCollection<ItemProperties2>(); ItemCollection.Add(new ItemProperties2 { Color1 = new SolidColorBrush(Colors.LightGray), Color2 = new SolidColorBrush(Colors.Brown) }); ItemCollection.Add(new ItemProperties2 { Color1 = new SolidColorBrush(Colors.Cyan), Color2 = new SolidColorBrush(Colors.Red) }); DataContext = ItemCollection; } } public class ItemProperties { private string m_Text1; public string Text1 { get { return m_Text1; } set { m_Text1 = value; } } private string m_Text2; public string Text2 { get { return m_Text2; } set { m_Text2 = value; } } } public class ItemProperties2 : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public ItemProperties2() { } private Brush m_Color1; public Brush Color1 { get { return m_Color1; } set { m_Color1 = value; OnPropertyChanged("Color1"); } } private Brush m_Color2; public Brush Color2 { get { return m_Color2; } set { m_Color2 = value; OnPropertyChanged("Color2"); } } protected void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(name)); } }
It seems that "non-INotifyPropertyChanged property" is given priority over "INotifyPropertyChanged property".
I think the problem is a little foolish in now. But If your code is quite large amount, you may not be able to find the problem immediately.
I write previous blog post as the answer for the problem. Please check it also.
GetList メソッドで ItemsSource を上書きしたために、XAML 上の ItemsSource="{Binding}" (つまり DataContext の適用) が無効になった、というのが主な原因です。
ReplyDelete今回はコレクション自体についての議論であって、中のアイテムが INotifyPropertyChanged かどうかは関係ありません。
以下に、データバインディングについて補足を書いておきます。
コントロールに DataContext が設定されているだけでは何も起こりません。
ItemsSource="{Binding}" のように設定して初めて ItemsSource が DataContext にバインドされます。
ちなみに、ItemsSource = items のように直接代入する行為はデータバインディングではありません。