I have Two Classes:
Fruit
has two data members FruitName
and FruitColor
Presentation
also has two members ForeColor
and FontName
A ListBox's ItemsSource
property is set to List<Fruit>
. And the fruits are listed.
However, I want to change FontFamily and Foreground of the TextBlock control, which should reflect immediately as I set the Presentation instance to the ListBox.
The problem is that
When I am calling the btnChangeColor_Click()
, I receive an exception " Object reference not set to an instance of an object ". In the INotifyPropertyChanged()
method. Exactly here...
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); });
I want to set ListBox with some Fruits object showing FruitName and FruitColor. I also want to change font names and the foreground of the TextBlock showing the FruitName and the FruitColor, so that changing the color and font name should reflect immediately
TestingRealTimeUIUpdate.xaml
<Page
x:Class="dataStorage_And_AppSettings.TestingRealTimeUIUpdate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:dataStorage_And_AppSettings"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<ListBox x:Name="lstFruits" Height="400" Background="Aqua">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="lblFruitName" Text="{Binding Fruits.FruitName}" Foreground="{Binding Presentations.ForeColor}" FontFamily="{Binding Presentations.FontName}" />
<TextBlock x:Name="lblFruitColor" Text="{Binding Fruits.FruitColor}" Foreground="{Binding Presentations.ForeColor}" FontFamily="{Binding Presentations.FontName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="lstColors" Height="175" Background="Goldenrod" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="lblFruitName" Text="FontColors And Font Name" Foreground="{Binding Presentation.ForeColor}" FontFamily="{Binding Presentation.FontName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="btnReloadFruits" Content="ReloadBasket" Click="btnReload_Click" />
<Button x:Name="btnChangeColor" Content="ChangeColor" Click="btnChangeColor_Click" />
</StackPanel>
</Grid>
</Page>
The TestingRealTimeUIUpdate.CS
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace dataStorage_And_AppSettings
{
public sealed partial class TestingRealTimeUIUpdate : Page
{
private Comp FruitBasket;
private List<Presentation> PresentationForFruitBasket = new List<Presentation>
{
new Presentation { FontName = "Arial", ForeColor = new SolidColorBrush(Colors.Green) },
new Presentation { FontName = "Verdana", ForeColor = new SolidColorBrush(Colors.Yellow) },
new Presentation { FontName = "Times New roman", ForeColor = new SolidColorBrush(Colors.Brown) },
new Presentation { FontName = "Tahoma", ForeColor = new SolidColorBrush(Colors.Red) },
};
private List<Fruit> FruitForFruitBasket = new List<Fruit>
{
new Fruit { FruitName= "Mango", FruitColor="Yellow" },
new Fruit {FruitName = "Banana", FruitColor= "Yellow" },
new Fruit { FruitName="Grapes", FruitColor="Green"},
new Fruit {FruitName="Tomato", FruitColor="Red" }
};
public TestingRealTimeUIUpdate()
{
this.InitializeComponent();
}
private void btnReload_Click(object sender, RoutedEventArgs e)
{
List<Comp> lstFruitBasket = new List<Comp>();
foreach( var item in FruitForFruitBasket)
{
FruitBasket = new Comp();
FruitBasket.Fruits = item;
FruitBasket.Presentations = PresentationForFruitBasket.ElementAt(2);
lstFruitBasket.Add(FruitBasket);
}
lstFruits.ItemsSource = lstFruitBasket;
}
private void btnChangeColor_Click(object sender, RoutedEventArgs e)
{
Random rnd = new Random();
FruitBasket.Presentations = PresentationForFruitBasket.ElementAt(rnd.Next(0, 3));
}
}
public class Comp : BindableBase
{
Fruit fruits = new Fruit();
Presentation presentations = new Presentation();
public Fruit Fruits
{
get { return fruits; }
set { SetProperty(ref fruits, value); }
}
public Presentation Presentations
{
get { return presentations; }
set { SetProperty(ref presentations, value); }
}
}
public class Fruit:BindableBase
{
private string fruitname;
private string fruitcolor;
public string FruitName
{
get { return fruitname; }
set { SetProperty(ref fruitname, value); }
}
public string FruitColor
{
get { return fruitcolor; }
set { SetProperty(ref fruitcolor, value); }
}
}
public class Presentation : BindableBase
{
private SolidColorBrush forecolor;
private string fontname;
public SolidColorBrush ForeColor
{
get { return forecolor; }
set { SetProperty(ref forecolor, value); }
}
public string FontName
{
get { return fontname; }
set { SetProperty(ref fontname, value); }
}
}
}
The BindableBase.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Core;
namespace IQ.Main.ViewModels
{
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private CoreDispatcher dispatcher;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (Object.Equals(storage, value))
{
return false;
}
storage = value;
NotifyPropertyChanged(propertyName);
return true;
}
internal virtual async void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
try
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
});
}
catch (Exception ex) { Debug.WriteLine(ex.Message); }
}
}
}
}
You can do something like this:
<ListBox Foreground="{x:Bind Foreground}" />
This works if the Foreground property is in your code-behind.
You can do something like this:
<ListBox Foreground="{Binding Foreground}" />
This works if the Foreground property is in your view-model.
You can also do this:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" Foreground="{Binding Foreground}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This works if the Foreground property is in your model
Remember, you can always create a composite object. Like this:
class MyObject
{
public FruitObject Fruit { get; set; }
public PresentationObject Presentation { get; set; }
}
This will let you pass in multiple objects to any
ItemControl
.
Make sense? Best of luck.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.