WPF combo box text converter when IsEnabled changes - wpf

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
}

Related

WPF ListBoxItem IsSelected property selects only for an instant

I have a ListBoxItem template with a TextBox element within. When the user clicks the TextBox, I should make the ListBoxItem as the SelectedItem of the ListBox.
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Margin="4,0,4,0">
<TextBlock Text="{Binding Path=Value1, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding Path=Hint, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" />
<TextBox x:Name="TextField"
Margin="2,0,0,0"
Width="{Binding Path=ActWidth, Mode=OneWay}"
Visibility="{Binding Path=VisibleAct, Mode=OneWay}"
/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I have the following Trigger to make the selection:
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
Unfortunately, it works only for
an instant, when I change the focus, the selection disappears.
If I remove the trigger, it works normally but selecting the TextBox does not trigger the selection.
What should I do to make the selection permanent?
Your sample doesn't work because, if the trigger is false, your ListBoxItem is getting the value as it had before triggering. Your ListBoxItem is like 'ehmm, what I was..'.
So you have to set its SelectedValue by adding a default setter that binds its IsSelected state:
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode="OneWay", RelativeSource={RelativeSource Self}}" />
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
Setting default setter for IsSelected as OneWay binding to itself will do the job. It will set IsSelected as it was, when the trigger is false.
You could write some code to set the SelectedItem property of the ListBox. You could handle the GotKeyboardFocus event for the TextBox:
<ListBox x:Name="lb2">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Margin="4,0,4,0">
<TextBlock Text="{Binding Path=Value1, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding Path=Hint, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" />
<TextBox x:Name="TextField"
Margin="2,0,0,0"
Width="{Binding Path=ActWidth, Mode=OneWay}"
Visibility="{Binding Path=VisibleAct, Mode=OneWay}"
GotKeyboardFocus="TextField_GotKeyboardFocus"
/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private void TextField_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
lb2.SelectedItem = textBox.DataContext;
}

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 update source trigger

I've added triggers for combobox, i.e.
When combo box is 'Disabled' then 'Text' property should set to '1'
and added updatesourcetrigger to property changed.
When combo box is 'Enabled' then 'Text' property should be selected one and added
update source trigger to property changed.
But the problem is I'm unable to call the update source trigger when combo box is Disabled and 'Text' property is set to '1'.
Below is the XAML code snippet:
<ComboBox Name="cmbIntervals"
Grid.Row="5"
Grid.Column="1"
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsEnabled="{Binding ElementName=chkRollingInterval,
Path=IsChecked}"
ItemsSource="{Binding Source={x:Static es:MasterParameters.Instance},
Path=NoOfIntervals}"
Tag="{Binding Path=[NoOfIntervals], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
>
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="1"/>
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Mode=TwoWay, UpdateSourceTrigger=Default}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
From above XAML code when ever i updated 'Text' property to '1' for combo box 'Disabeld' mode i need to update this '1' value to the source property i.e. 'Tag' and from there to 'NoOfIntervals' but it doesn't happening.
Thanks,
Nag

Understandig DataTrigger

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.

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>

Resources