Reputation: 55
I'm trying to dynamically change this Foreground value when the name "David" is entered:
<RichTextBox x:Name="richTextBox" Height="100" Width="366">
<FlowDocument>
<Paragraph>
<Run Text="{Binding Customer.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Foreground="{Binding Customer.TColor}"/>
</Paragraph>
</FlowDocument>
</RichTextBox>
Where I'm binding Foreground to TColor. I've changed the color at set to confirm the binding works properly.
Inside of my models my customer class has the following constructor, TColor Property, and OnPropertyChanged method:
public class Customer : INotifyPropertyChanged, IDataErrorInfo
{
private string name;
private string tColor;
private string defaultColor = "#000000";
/// <summary>
/// constructor
/// </summary>
public Customer(String customerName)
{
Name = customerName;
TColor = defaultColor;
}
public string TColor
{
get
{
return tColor;
}
set
{
tColor = defaultColor;
OnPropertyChanged("TColor");
}
}
/// <summary>
/// getter and setter
/// </summary>
public String Name
{
get
{
return name;
}
set
{
name = value;
OnPropertyChanged("Name");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
My view models CustomerViewModel class has my ChangeColor method where if its called it should set the color to that corresponding value. A concern I have in this class is how my CanUpdate method is used by my later mentioned ChangeColorCommand Class. Another problem I see but don't know the answer to is if I can use UpdateCommand twice in the same place I'm initializing the other. Yet, the UpdateCommand for CustomerUpdateCommand does what it should.
internal class CustomerViewModel
{
private Customer customer;
private CustomerInfoViewModel childViewModel;
/// <summary>
/// init new instance of the class
/// </summary>
public CustomerViewModel()
{
//you could use this for a new Twitter user
customer = new Customer("David");
childViewModel = new CustomerInfoViewModel();
UpdateCommand = new ChangeColorCommand(this);
UpdateCommand = new CustomerUpdateCommand(this);
}
public bool CanUpdate
{
get
{
if (!(Customer.Name == "David"))
{
return false;
}
return true;
}
}
/// <summary>
/// Gets the customer instance
/// </summary>
public Customer Customer
{
get
{
return customer;
}
}
/// <summary>
/// gets the update command for the view model
/// </summary>
public ICommand UpdateCommand
{
get;
private set;
}
public void ChangeColor()
{
Customer.TColor = "#0000ff";
}
/// <summary>
/// saves changes made to the customer instance
/// </summary>
public void SaveChanges()
{
CustomerInfoView view = new CustomerInfoView()
{
DataContext = childViewModel
};
childViewModel.Info = Customer.Name + " was updated in the database.";
view.ShowDialog();
//Debug.Assert(false, String.Format("{0} was updated.", Customer.Name));
}
}
A likely place for me to have made a mistake is here in my ChangeColorCommand:
internal class ChangeColorCommand : ICommand
{
private CustomerViewModel viewModel;
public ChangeColorCommand(CustomerViewModel viewModel)
{
this.viewModel = viewModel;
}
#region ICommand members
public event System.EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return viewModel.CanUpdate;
//return String.Equals(this, "David")
}
public void Execute(object parameter)
{
viewModel.ChangeColor();
}
#endregion
}
In case I missed a detail about my code the entire project can be found at this repository
Upvotes: 1
Views: 656
Reputation: 5236
Here is the way to do this...
<RichTextBox x:Name="richTextBox" Height="100" Width="366">
<FlowDocument>
<Paragraph Foreground="{Binding Customer.Color}">
<Run Text="{Binding Customer.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
</Paragraph>
</FlowDocument>
</RichTextBox>
Where...
public Brush Color
{
get
{
return name.Length > 0 && name[0] == 'D' ? Brushes.Red : Brushes.Black;
}
}
And here is the key part...
/// <summary>
/// getter and setter
/// </summary>
public String Name
{
get
{
return name;
}
set
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
}
}
Note the following:
Upvotes: 2
Reputation: 8263
How about a data trigger
<Style TargetType="RichTextBox">
<Setter Property="Foreground"
Value="PutYourdefaultColor" />
<Style.Triggers>
<DataTrigger Binding="{Binding Customer.Name}"
Value="David">
<Setter Property="Foreground"
Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
Upvotes: 2
Reputation: 1574
Not exactly sure what the program is supposed to do but I see 2 issues:
UpdateCommand
twice, thus your ChangeColor
is never
going to work TColor
property setter you don't use value
Also, there is an issue with binding in RichTextBox
. Once you delete or change "David" you split or completely delete the Run
. Just try it with another TextBox
bound to Name
and observe the behaviour
Upvotes: 0