DataTrigger does not change Text property
The local value assigned to the TextBlock's Text property has higher precedence than the value provided by the Setter in the DataTrigger. See Dependency Property Value Precedence for details.
Set the initial Text value by another Setter:
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Unclicked"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Clicked,
Source={x:Static Application.Current}}"
Value="{StaticResource True}">
<Setter Property="Text" Value="Clicked" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
The error message you see when you use the Boolean resource is just the XAML designer complaining. There is no error at runtime.
TextBox's Text set through DataTrigger not updating the property value in Model
In such cases I normally prefer ViewModel / Model doing the "clear" part of the functionality,
hence in your case I'd normally do something like:
public bool IsSelected {
get {
return _isSelected;
}
private set {
if (value == _isSelected)
return;
RaisePropertyChanging(() => IsSelected);
_isSelected = value;
RaisePropertyChanged(() => IsSelected);
if (_isSelected == false)
Amount = string.Empty
}
}
That way the View does not hold responsibility for any logic and thus doesn't need the DataTrigger
at all
Update:
The Problem with your code is when you set the Text
with a Binding in the TextBox
it takes precedence over the value you set in the Style
for the Text property. You can check this by using this:
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text"
Value="{Binding Path=Amount,
Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}"
Value="false">
<Setter Property="Text"
Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
This will now clear the Text when the CheckBox
is checked, however it will not be updating your Binding(Amount
) since essentially your Binding is only active when the CheckBox
is selected.
DataTrigger inside ItemTemplate-DataTemplate not triggering upon property change
The class where the IsOpened
property is defined should implement the INotifyPropertyChanged interface and and raise the PropertyChanged
event when the IsOpened
property is set:
class DataObject : INotifyPropertyChanged
{
private bool _isOpened;
public bool IsOpened
{
get { return _isOpened; }
set { _isOpened = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
ContentStringFormat never changes by Setter Property in DataTrigger
There are a lot of discussions, using Labels and ContentStringFormat
does not work like expected or desired:
- WPF StringFormat on Label Content
- StringFormat VS ContentStringFormat
- ...
The reason seems to be the template based implementation under the hood, since the content also could contain other data than strings. To solve your problem, my proposal is to use a TextBlock, which works quite smooth like this:
<StackPanel>
<CheckBox IsChecked="{Binding MyFlag}"/>
<TextBlock HorizontalAlignment="Center" FontSize="40">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding MyFlag}" Value="False">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}+++'}" />
</DataTrigger>
<DataTrigger Binding="{Binding MyFlag}" Value="True">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}???'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
DataTrigger applied to text property of a Textbox causes its binding to stop working
You are looking for a watermark textbox. The standard WPF TextBox
does not support this behavior.
However, there are 3rd party controls available such as the one pointed out by Frank: http://wpfplayground.com/2014/06/30/watermark-behavior-for-textbox/
Ways to do your own can be found at Watermark / hint text / placeholder TextBox in WPF
Finally, you can always just overlay your own TextBox or TextBlock over the real one and hide it on focus, which will do basically the same thing.
Data trigger not firing off correct string value
Here you go:
<TextBox x:Name="first" FontSize="14" TabIndex="1" Background="Black" BorderThickness="5" Foreground="White" Margin="29,10,132,272">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="BorderBrush" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="{x:Null}">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
DataTrigger to change TextBlock text on ToggleButton click
"a solution consistent with MVVM" is a misconception when you are styling a control. This is only a view element and should not depend on any view model. MVVM is not relevant here.
The TextBlock in the ContentTemplate should show the ToggleButton's Content
property by Text="{Binding}"
, and the Content property should be set by a Style Setter and changed by a Style Trigger on the ToggleButton's IsChecked
property.
Also note that DataType="{x:Type ToggleButton}"
on the ContentTemplate is pointless and incorrect. DataType is meant for automatic usage of DataTemplate resources, which does not happen here. And it is supposed to match the type of the Content, which is not the type of the control.
<ToggleButton ...>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image ...>
...
</Image>
<TextBlock Text="{Binding}" Margin="5"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Content" Value="Enable Editing"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Cancel Editing"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
XAML DataTrigger not updating
We cannot see how you are updating the IsFilterOn
property from true
to false
but if you are directly changing the property of one of the FilterModel
instances in the list, then the property changed event will not be invoked.
The ObservableCollection
will execute property changed events when you add or remove something from the list, but it is not watching objects' properties.
You have 2 options, either invoke Property Changed events from your FilterModel
anytime IsFilterOn
is updated or change all of the property values you need to and then manually execute property changed on the list. If you are updating multiple FilterModel
s at the same time, performance would probably be better with the second option.
Option 1:
public class FilterModel : INotifyPropertyChanged {
public string UpColour { get; set; }
public string DownColour { get; set; }
private bool _isFilterOn = false;
public bool IsFilterOn {
get { return _isFilterOn; }
set {
_isFilterOn = value;
NotifyPropertyChanged(); // Anytime this property is changed Property Changed will be executed
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Option 2:
public class FilterViewModel {
private ObservableCollection<FilterModel> _filters;
public ObservableCollection<FilterModel> Filters {
get => _filters ?? (_filters = new ObservableCollection<FilterModel>());
set {
_filters = value;
NotifyPropertyChanged();
}
}
public void ToggleFilters() {
// some logic
Filters[0].IsFilterOn = true; // Make all property changes
NotifyPropertyChanged(nameof(Filters)); // Tell the UI that the list has been updated and to refresh the data
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Related Topics
For Loop Not Returning Expected Value - C# - Blazor
Can You Configure Log4Net in Code Instead of Using a Config File
Programmatically Add an Application to Windows Firewall
.Net - Windowstyle = Hidden VS. Createnowindow = True
Get the Property, as a String, from an Expression<Func<Tmodel,Tproperty>>
How to Hide "Chrome Is Being Controlled by Automated Software" Infobar Within Chrome V76
Selecting a Textbox Item in a Listbox Does Not Change the Selected Item of the Listbox
Is Nameof() Evaluated at Compile-Time
How to Create a Custom Messagebox
How to Get Around the "'" Problem in SQLite and C#
How to Check If Any Flags of a Flag Combination Are Set
How to Do a Sha1 File Checksum in C#