Understandig DataTrigger - wpf

I have a ComboBox and a TextBox and want to enable/disable TextBox only, when first item is selected in ComboBox.
This code works: (disable when first item is selected)
<ComboBox SelectedIndex="{Binding Mode}">
<ComboBoxItem>Mode 1</ComboBoxItem>
<ComboBoxItem>Mode 2</ComboBoxItem>
<ComboBoxItem>Mode 3</ComboBoxItem>
</ComboBox>
<TextBox Text="{Binding ValueNotForMode1}">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding ="{Binding Mode}" Value="0">
<Setter Property="TextBox.IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
This one doesn't work: (enable when first item is selected)
<ComboBox SelectedIndex="{Binding Mode}">
<ComboBoxItem>Mode 1</ComboBoxItem>
<ComboBoxItem>Mode 2</ComboBoxItem>
<ComboBoxItem>Mode 3</ComboBoxItem>
</ComboBox>
<TextBox IsEnabled="False" Text="{Binding ValueForMode1}">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding ="{Binding Mode}" Value="0">
<Setter Property="TextBox.IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Isn't it possible to enable a control via DataTrigger?
Or how can I tell the control, what to do, when the Trigger not occures?

Move IsEnabled="False" from your TextBox to your TextBox.Style.
<Setter Property="TextBox.IsEnabled" Value="False" />
See Dependency Property Value Precedence for clearer understanding.

Related

Change my binding Check-Box style when mouse over ListViewItem

So i have ListView with Check-Box cell:
<ListView.Resources>
<DataTemplate x:Key="CheckBoxCell">
<CheckBox IsChecked="{Binding Path=IsChecked}"/>
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridViewColumn Width="30" x:Name="gridViewColumnIsChecked" CellTemplate="{StaticResource CheckBoxCell}"/>
</ListView.View>
And i have ListViewItem style with several triggers like IsMouseOver so when IsMouseOver is True i am change my Background color for example.
So i want to change my Check-Box style\color when mouse over ListViewItem.
How i can i achieve that ?
Use this snippet:
<DataTemplate x:Key="CheckBoxCell">
<CheckBox>
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</DataTemplate>
The solution is to create a DataTrigger, which binds to parent ListViewItem.IsMouseOver property, like another answer shows
However, the trigger can be also placed in <DataTemplate.Triggers> to make markup shorter. In that case Setter uses TargetName to access the correct control.
<DataTemplate x:Key="CheckBoxCell">
<CheckBox IsChecked="{Binding Path=IsChecked}" Name="Chk" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter TargetName="Chk" Property="Background" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

SelectedItem value of combo box gets empty on updating from viewmodel in wpf

I have created a combo box in each datagrid row. The following piece of code is used to create the combo box:
<ComboBox Width="166"
ItemTemplate="{StaticResource GridBinding}"
SelectedItem="{Binding Path=Car, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, IsAsync=True}"
SelectedValue="{Binding Path=Car, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, IsAsync=True}">
<ComboBox.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource GroupHeader}" />
</ComboBox.GroupStyle>
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=Cars}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=DataGridCell}}" Value="True">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.GroupedCars, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
The "Car" property for binding "SelectedItem" in combo box is an object of class "Car" holding some properties like id, name, etc.
The problem I am facing is that when I update the value of "Car" property and call "NotifyPropertyChanged" in its setter, then the value of "SelectedItem" in combo box goes blank/empty.
Please suggest.
The SelectedItem can no longer be found in the Collection (when you update your ItemSource) and gets set to null.
I've simplified your XAML to demonstrate
<ComboBox ItemsSource="{Binding Cars}"
SelectedItem="{Binding Car}">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="SelectedItem" Value="{x:Null}">
<Setter Property="SelectedIndex" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Now the first Item will get selected when you update.

WPF combo box text converter when IsEnabled changes

I've to change the Text property of a combo box when IsEnabled sets to false and it can manually selects field from the items source when IsEnabled is true from the same control, is this possible?
XAML:
<ComboBox Name="cmbIntervals"
Grid.Row="5"
Grid.Column="1"
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsEnabled="{Binding ElementName=chkBox,
Path=IsChecked}"
ItemsSource="{Binding Source={x:Static res:Parameters.Instance},
Path=Intervals}"
Text="{Binding [Intervals], Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" >
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="1"/>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Just check in ViewModel
if(!IsChecked)
{
TextProperty="1"; //Propery to bind to ComboBox Text
}

Combobox ItemTemplate and foreground

I have a comboBox that is bound to a list of strings from my viewModel. What I am trying to do is have the foreground of a comboBox item be set to a different color if a property in my viewModel is true:
<ComboBox x:Name="myComboBox" ItemsSource="{Binding Names}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ...}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Foreground" Value="Navy"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I am not sure what to bind the Text of the TextBlock to. All I want is to display the list of strings. I always end up with a dropdown that has the items but they are not visible. I tried removing the style trigger thinking that maybe I was screwing up there, but that didn't help.
Am I taking the right approach? Will the ComboBox.ItemTemplate correctly look at my viewModel (which is the data context) when searching for IsActive or is that binding incorrect as well?
The DataContext for each ComboBoxItem is a string so
For the TextBlock, bind to the DataContext like Text="{Binding}
For the DataTrigger to be able to find IsActive, use RelativeSource in the binding
<ComboBox x:Name="myComboBox" ItemsSource="{Binding Names}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox}},
Path=DataContext.IsActive}"
Value="True">
<Setter Property="Foreground" Value="Navy"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

How to disable a databound ListBox item based on a property value?

Does anyone know if and how one can disable items in a databound ListBox based on the value of a property?
Preferably I would like a DataTrigger which, when a certain property is false, disables this item (make it impossible to select) without affecting other items in the ListBox.
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="textBlock" Text="{Binding Description}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
??
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can use ItemContainerStyle:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding YourPropertyName}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Resources