Datatrigger Does Not Change Text Property

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 FilterModels 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



Leave a reply



Submit