Enable or disable a TextBox depending on the selected ComboBoxItem - wpf

I have a Combobox and some text Boxes, I want to disable some text boxes deppending on the selected item in the ComboBox.
the Xaml code:
<ComboBox Name="Combo" ItemsSource="{Binding ModeReglementList}"}"/>
<TextBox IsEnabled="{Binding ElementName=Combo, .........}"/>
What is the simplest way to accomplish this dependency control in WPF?

You could apply a Style with data triggers to the TextBox.
In the below markup, the TextBox will be disabled when you select "b" in the ComboBox:
<ComboBox Name="Combo" ItemsSource="{Binding ModeReglementList}" />
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=Combo}" Value="b">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
View Model:
public IEnumerable<string> ModeReglementList { get; } =
new string[] { "a", "b", "c" };
You can add other triggers to trigger on different values.

Related

WPF Editable Combobox does not change SelectedValue while typing

I defined a Combobox whose SelectedValue is binded to a property on the view model VM.SelectedServiceTypeId
<ComboBox Name="ServiceTypeComboBox"
IsEditable="True"
Grid.Row="1"
Grid.Column="1"
Margin="5"
DisplayMemberPath="ServiceTypeName"
ItemsSource="{Binding ServiceTypes,Mode=TwoWay}"
SelectedValue="{Binding SelectedServiceTypeId, Mode=TwoWay}"
SelectedValuePath="ServiceTypeId"
Loaded="ServiceTypeComboBox_Loaded"
/>
The value is correctly updated when the user selects an item in the dropdown menu, but cause the combobox IsEditable the user is able to type whatever he wants that it's not a value in the ItemSource. In this case the SelectedValue does NOT change.
What I need to do is to enable a button when the SelectedValue is among those in the ItemsSource.
Do you have some hint?
Your wpf combobox has a property "Text" that contains the text input by the user. You will have to write some code to check if the entered text matches anything in your itemssource.
<Button Content="Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ServiceTypeComboBox, Path=SelectedValue}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

WPF combobox selected index

I have a combobox which I'm setting it's itemsSource after getting it from a database, for some reason the combobox doesn't show the first item.
My comboBox:
<ComboBox Text="Add To Message:" ItemsSource="{Binding Messages}" SelectedValue="{Binding SelectedMessage}" Style="{StaticResource comboStyle}"/>
My style:
<Style TargetType="ComboBox" x:Key="comboStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectedItemId}" Value="-1">
<Setter Property="SelectedIndex" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of setting SelectedIndex you should set SelectedMessage:
// get data from db...
SelectedMessage = Messages.FirstOrDefault();

WPF Default Value (using Style Trigger) with Binding

I'm new to WPF so please bear with me. I have a ComboBox on my WPF window, the ItemSource property is bound to a List of strings property (Countries) and the SelectedItem is bound to a string property (SelectedCountry). Both of these properties are in the code behind - and I'm setting the DataContext to "this" (i.e. the Window).
The ComboBox xaml is:
<ComboBox Name="CountryComboBox"
VerticalAlignment="Center"
Width="200"
ItemsSource="{Binding Path=Countries, Mode=OneTime}"
SelectedItem="{Binding Path=SelectedCountry, Mode=TwoWay}">
</ComboBox>
I wanted to have a default "- Please Select -" option that is displayed when an item is not selected, therefore I placed the following xaml in App.xaml:
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="SelectedItem" Value="{x:Null}">
<Setter Property="IsEditable" Value="true" />
<Setter Property="IsReadOnly" Value="true" />
<Setter Property="Text" Value="- Please Select -" />
</Trigger>
</Style.Triggers>
</Style>
When my window is first displayed, the combobox does have the "- Please Select -" text as expected. When I then select a value in the combobox, the SelectedCountry gets populated appropriately, but then when I assign "null" to the SelectedCountry property the combobox still has the same selected country when I'd expect it to go back to "- Please Select -". What am I doing wrong?
Thanks.
It may be a better option not to modify the ComboBox and simply overlay a TextBlock over the ComboBox when the SelectedItem is null.
Just wrap the ComboBox and a TextBlock in a Grid and set a DataTrigger on the TextBlock to check if the SelectedItem is null and toggle its Visibility
Example:
<Grid>
<ComboBox x:Name="combo" ItemsSource="{Binding Countries}" SelectedItem="{Binding SelectedItem}" />
<TextBlock x:Name="textblock" Text="- Please Select -" Margin="5,3,0,0" IsHitTestVisible="False">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem,ElementName=combo}" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
Result:
You need to insert a record into the Countries list that has a value of null and the name " - Please Select - ".
Alternatively I suppose you could extend the ComboBox control and write your own so that you could specify the null vale in the list without having to put a record into the Countries selection.
But of the two, it is much easier to just add a record to Countries.

How to bind DataGridTemplateColumn.Visibility to a property outside of DataGrid.ItemsSource?

I need to bind the Visibility of a DataGridTemplateColumn to a property outside of the DataGrid.ItemsSource,because i need to bind this column in the all the rows to one property inside the ViewModel,but as far as i know you just can bind that to something inside the ItemsSource or you should use ElementStyle and EditingElementStyle
I've Already tried this code:
<DataGridTemplateColumn Header="post"
Visibility="{Binding DataContext.ProjectPostVisibility
, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MvvmCommonControl:DataGrid}}"/>
And i'm Sure my binding is correct because it works fine when i bind the DataGridCell.Visibility like below:
<DataGridTemplateColumn Header="post">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Visibility" Value="{Binding DataContext.ProjectPostVisibility,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MvvmCommonControl:DataGrid}}"/>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn >
Your binding is correct, but it won't work with DataGridTemplateColumn directly because it's not in the visual tree. So it's not inherting DataContext.
You need to bind the DataGridTemplateColumn from code behind. Here is a demo that shows a way of doing it.
As mentionned in other answers, the column isn't part of the visual/logical tree and doesn't inherit from FrameworkElement meaning it has no DataContext. That's why your binding doesn't work.
However you can add a dummy (collapsed) FrameworkElement at a level where the DataContext is what you're looking for (so taking your example, it'd be at the DataGrid's level), collapse it and use it as the Source of your Binding with the x:Reference markup extension.
Here's an example :
<FrameworkElement x:Name="Proxy" Visibility="Collapsed"/>
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="post"
Visibility="{Binding DataContext.ProjectPostVisibility, Source={x:Reference Name=Proxy}}"/>
</DataGrid.Columns>
</DataGrid>
Add this setter in the DataGridTemplateColumn.CellStyle and done:
<Setter Property="Visibility" Value="{Binding DataContext.isVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"/>
If you need more help look at my example below.
I want the Remove button to not be visible at the project level. First you have to make sure you have a isVisible property in your view model:
private System.Windows.Visibility _isVisible;
public System.Windows.Visibility isVisible
{
get { return _isVisible; }
set
{
if (_isVisible != value)
{
_isVisible = value;
OnPropertyChanged("isVisible");
}
}
}
Then:
if (isProj == false)
this.model.isVisible = Visibility.Visible;
else
this.model.isVisible = Visibility.Collapsed;
XAML:
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<Button x:Name="btnRemove" Content="X">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="ExtraBold" />
<Setter Property="FontSize" Value="50" />
</Style>
</Button.Style>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Red"/>
<Setter Property="Visibility" Value="{Binding DataContext.isVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"/>
</Style>
</DataGridTemplateColumn.CellStyle>

Is there a way to get the DataContext for a bound Property

Is there a way in code to get the the DataContent for the Text Property of the ComboBox defined below?
<ComboBox Height="21" Text="{Binding Path=Field1.Value}">
<ComboBox.Resources>
<Style TargetType="ComboBox">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Field2.Value}" Value="">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Resources>
</ComboBox>
Currently the DataContext of the ComboBox is the user control in which it lives. Which makes sense because I want my Text bound to one property and my DataTrigger to be bound to another property. But I need to get the DataContext that's being bound to for the Text property.
Something like this should do it:
Binding binding = BindingOperations.GetBinding(yourComboBox, ComboBox.TextProperty);
object theDataContext = binding.Source;

Resources