Bind IsEnabled property to Boolean in WPF - c#

I have a TextBox which needs to be enabled / disabled programmatically. I want to achieve this using a binding to a Boolean. Here is the TextBox XAML:
<TextBox Height="424" HorizontalAlignment="Left"
Margin="179,57,0,0" Name="textBox2"
VerticalAlignment="Top" Width="777"
TextWrapping="WrapWithOverflow"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
AcceptsReturn="True" AcceptsTab="True"
Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=TextBoxEnabled}"/>
Notice the Text property is bound as well; it is fully functional, which makes me think it is not a DataContext issue.
However, when I call this code:
private Boolean _textbox_enabled;
public Boolean Textbox_Enabled
{
get { return _textbox_enabled; }
set
{
OnPropertyChanged("TextBoxEnabled");
}
}
It does not work. To give further information, the TextBox_Enabled property is changed by this method:
public void DisabledTextBox()
{
this.Textbox_Enabled = false;
}
..which is called when a key combination is pressed.

Here are your little typos!
private Boolean _textbox_enabled;
public Boolean TextboxEnabled // here, underscore typo
{
get { return _textbox_enabled; }
set
{
_textbox_enabled = value; // You miss this line, could be ok to do an equality check here to. :)
OnPropertyChanged("TextboxEnabled"); //
}
}
Another thing for your xaml to update the text to the vm/datacontext
Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding TextBoxEnabled}"/>

Related

show/hide control textbox based on combobox selected WPF

I have a WPF/MVVM project in C #/FrameWork 4.0
In my view I have two ControlBox "NoRSAC" and "LieuRSAC"
<View:StateControlTextBox
x:Name="NoRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Text="{Binding UserVM.No_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch" />
<View:StateControlTextBox
x:Name="LieuRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Text="{Binding UserVM.Lieu_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch"/>
</Canvas>
And ControlComboBox "cmbFonction"
<View:StateControlComboBox
x:Name="cmbFonction"
ReadOnlyControlState="Disabled"
IsReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
ItemsSource="{Binding ListeFonctions}"
SelectedValue="{Binding UserVM.Fonction, Mode=TwoWay}" Width="303" Margin="0" HorizontalAlignment="Left" Canvas.Left="97" Canvas.Top="108" />
I want to view the ControlBox "NoRSAC" and "LieuRSAC" when I select a particular valeure in the ComboBox "cmbFonction" and hide when it's another selected value
Thank you for your help
In the set method of the property Fonction, you can check the value and update another property that you should introduce in your view model and that is of type System.Windows.Visibility. In the following example, I call this property TextBoxVisibility:
public class UserVM : INotifyPropertyChanged
{
private Visibility _textBoxVisibility;
public Visibility TextBoxVisibility
{
get { return _textBoxVisibility; }
set
{
_textBoxVisibility = value;
OnPropertyChanged();
}
}
public string Fonction
{
get { return _fonction; }
set
{
_fonction = value;
OnPropertyChanged();
if (value == "Value A")
TextBoxVisibility = Visibility.Hidden;
else
TextBoxVisibility = Visibility.Visible;
}
}
// Other members omitted for sake of simplicity.
}
Please note that you need to implement INotifyPropertyChanged (directly or indirectly) so that the changes of the property values are forwarded to the bindings that can in turn update the dependency properties of the controls in your view.
Thus you must not forget to add an additional binding to all of your text boxes in your view. Here is an example for that, the important part is the binding on Visibility:
<View:StateControlTextBox
x:Name="NoRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Visibility="{Binding UserVM.TextBoxVisibility}"
Text="{Binding UserVM.No_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch" />

WPF Combbox Wildcard Substring Search

I have the following properties set on my combobox-
<ComboBox ItemsSource="{Binding AllLines, Mode=OneWay}" Grid.Column="1" SelectedItem="{Binding SelectedLine}" Margin="4"
Visibility="{Binding ShowLines, Converter={StaticResource BoolToVisible}}" AlternationCount="2"
IsTextSearchEnabled="True" IsEditable="True" TextSearch.TextPath="SearchText" IsTextSearchCaseSensitive="False"
ItemContainerStyle="{StaticResource alternatingWithTriggers}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Margin="2,0,2,0" FontWeight="Bold" Text="{Binding Description}"
Visibility="{Binding Description, Converter={StaticResource NullVisibilityConverter}}"></TextBlock>
<TextBlock Margin="2,2,2,4" Text="{Binding Designator}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Following the suggestion outlined here I added a custom Search property that included the three properties I wanted to search against.
WPF: Changing a ComboBox's ItemTemplate removes the ability to jump down the list as you type. Any way to fix this?
public string SearchText {get { return string.Format("{0} | {1} | {2}", Description, ID, Designator); }}
My question is, can I do a wildcard or substring search on my concatenation of properties?
Found an idea here from which I modeled my solution-
http://jacobmsaylor.com/?p=17
I made some small changes such as listening to the KeyUp instead of the KeyDown and making the filter case-insensitive. I also added a check to make sure that the combo box text (the search text) was not null or empty.
In the code behind-
public SelectRouteSegmentDialog()
{
InitializeComponent();
LineComboBox.Items.Filter += FilterPredicate;
}
private bool FilterPredicate(object obj)
{
Line line = obj as Line;
if (string.IsNullOrEmpty(LineComboBox.Text)) return true;
if (line.SearchText != null)
{
if (line.SearchText.IndexOf(LineComboBox.Text, StringComparison.CurrentCultureIgnoreCase) >= 0)
{
return true;
}
return false;
}
else
{
//if the string is null, return false
return false;
}
}
private void combobox_KeyUp(object sender, KeyEventArgs e)
{
if ((e.Key == Key.Enter) || (e.Key == Key.Tab) || (e.Key == Key.Return))
{
//Formatting options
LineComboBox.Items.Filter = null;
}
else if ((e.Key == Key.Down) || (e.Key == Key.Up))
{
LineComboBox.IsDropDownOpen = true;
}
else
{
LineComboBox.IsDropDownOpen = true;
LineComboBox.Items.Filter += this.FilterPredicate;
}
}
And the xaml I set IsEditable=true, IsTextSearchEnabled=false and TextSearch.TextPath equal to the path I wanted displayed for my selected item (otherwise just the ToString was displayed). I also listend to the key up event-
<ComboBox ItemsSource="{Binding AllLines, Mode=OneWay}" Grid.Column="1" SelectedItem="{Binding SelectedLine}" Margin="4"
Visibility="{Binding ShowLines, Converter={StaticResource BoolToVisible}}" AlternationCount="2"
IsEditable="True" TextSearch.TextPath="SearchText" IsTextSearchEnabled="False"
ItemContainerStyle="{StaticResource alternatingWithTriggers}" x:Name="LineComboBox" KeyUp="combobox_KeyUp">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Margin="2,0,2,0" FontWeight="Bold" Text="{Binding DisplayText}"
Visibility="{Binding Description, Converter={StaticResource NullVisibilityConverter}}"></TextBlock>
<TextBlock Margin="2,2,2,4" Text="{Binding Designator}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
My question is, can I do a wildcard or substring search on my concatenation of properties?
Not using the built-in TextSearch mechanism; it's a prefix match only. You can specify the text directly, or provide the path to the property containing the text (as you have done), but you cannot change the matching behavior.
You will have to implement your own text search mechanism to get the kind of behavior you want. Try exploring the TextSearch source code for implementation ideas.

Textbox strange behavior when entering space

I am using Silverlight 5 and C#. My model (CustomerModel) implements INotifyDataErrorInfo interface to validate user input. The TextBox whose Text property is bound to a Property in the model, which is being validated on every keystroke (I have set UpdateSourceTrigge=PropertyChanged), is behaving strangely - When I enter space the cursor moves to the beginning of the TextBox. Very annoying.
<TextBox x:Name="txtDebtorName" Grid.Row="2" Grid.Column="1"
Text="{Binding SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True, NotifyOnValidationError=True}"
IsReadOnly="{Binding IsReadonly}" >
</TextBox>
Any Idea what is causing this behavior, and how to fix it?
The property in the model:
public string Name
{
get { return _Name; }
set
{
const string propertyName = "Name";
ValidateRequiredString(propertyName, value, Utility.GetTranslation("RequiredFieldDebtorName"));
_Name = value;
RaisePropertyChanged(propertyName);
}
}
The ValidateRequiredString() method takes the PropertyName, the value being set and an error Message.

IDataErrorInfo error message triggers, but no message is shown

Hello fellow programmers. I have this strange issue on Silverlight MVVM pattern using IDataErrorInfo. It's my first question made here in StackOverflow, so I hope I manage to explain it correctly. Here's the deal:
I Have this huge Job Register ChildWindow that has some controls that should only be enabled if a checkbox called HasPrevision is checked. The idea is: if the job has a Prevision, then all the controls related to the prevision are Enabled, otherwise, they are Disabled.
Now, if there is a prevision, the user MUST choose a Prevision Type in the PrevisionType ComboBox. So, if the HasPrevision checkbox is CHECKED, the PrevisionType must be selected, but if the HasPrevision checkbox is NOT CHECKED, the PrevisionType comboBox can be left unselected.
Here are the XAML for those controls (I won't show all the xaml here because it's rather big, but I believe that the problem can be solved just by showing those lines):
<!-- The HasPrevision CheckBox -->
<CheckBox Grid.Column="1"
Grid.Row="3"
x:Name="cbxHasPrevision"
IsChecked="{Binding SelectedJob.HasPrevision, Mode=TwoWay}"
Margin="0,20,2,0" />
<!-- The PrevisionType ComboBox -->
<telerik:RadComboBox Grid.Column="1"
Grid.Row="4"
x:Name="cmbPrevisionType"
IsEnabled="{Binding HasPrevision, Converter={StaticResource ControlesCadastroProcessoConverter}, ConverterParameter=IsEnabled}"
ItemsSource="{Binding PrevisionTypeList, Mode=OneWay}"
SelectedItem="{Binding SelectedJob.PrevisionType , Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True}"
Margin="0,4,48,4"
Height="22"
DisplayMemberPath="DsPrevisionType"/>
So, as you can see, the HasPrevision and the PrevisionType properties are binded to a property in my ViewModel called SelectedJob. SelectedJob is a Job object. All I want to do is use the IDataErrorInfo interface in my Job Class to identify if the PrevisionType is selected. Now, I can only require a PrevisionType if the HasPrevision property is "true", so my job class has this code for the IDataErrorInfo:
public string this[string columnName]
{
get
{
switch (columnName)
{
case "PrevisionType":
if (HasPrevision && (PrevisionType== null))
return "Select a PrevisionType";
break;
}
return null;
}
}
This sounds very logical to me. When I debug the code, it actually works: the switch identifies the columnName, it enters the case "PrevisionType" and it actually runs the return code inside the If statement returning the error message, not the default "return null" clause. But the error message don't show the error! Even worse: the combo box wont event validate automatically.
When the "Save" button is clicked, I check for errors and set the PrevisionType comboBox to the InvalidFocused state. The comboBox DOES get the red border around it indicating that it is in an error state, but the error message is blank. When I hover my mouse of the control, an empty small red box appears, with nothing on it.
Even more weird than that: if I REMOVE the "HasPrevision" check from the IF statement, leaving the code as follow, the message is shown and the control is validated automatically!!!
public string this[string columnName]
{
get
{
switch (columnName)
{
case "PrevisionType":
if (PrevisionType== null)
return "Select a PrevisionType";
break;
}
return null;
}
}
Everything I can think of is that since I'm trying to validate a property based on another property value, somewhere in the middle of the set's and get's the Silverlight environment gets "confused"? I don't know, I've been trying to find a solution for this for 2 days with no success.
Here are some of the other codes that I believe that are relevant.
The properties in my Job Class:
private bool _HasPrevision;
[DataMember]
public bool HasPrevision
{
get { return _HasPrevision; }
set
{
_HasPrevision= value;
RaisePropertyChanged("HasPrevision");
}
}
private PrevisionType.PrevisionType _PrevisionType { get; set; }
[DataMember]
public PrevisionType.PrevisionType PrevisionType
{
get { return _PrevisionType; }
set
{
_PrevisionType = value;
RaisePropertyChanged("PrevisionType");
}
}
My SelectedJob property in my ViewModel is:
public const string SelectedJobPropertyName = "SelectedJob";
private Objects.Register.Job.Job _SelectedJob = null;
public Objects.Register.Job.Job SelectedJob
{
get
{
return _SelectedJob;
}
set
{
if (_SelectedJob == value)
return;
var oldValue = _SelectedJob;
_SelectedJob = value;
RaisePropertyChanged(SelectedJobPropertyName , oldValue, value, true);
}
}
And my code for the Save Button is:
[...]
if(SelectedJob["PrevisionType"] != null)
{
VisualStateManager.GoToState(cmbPrevisionTypeControl, "InvalidFocused", true);
return;
}
[...]
Thanks in advance and I'm sorry if I got a little bit confused on explaining this.
EDIT 1: I had already read on those questions here, but they don't quite help me:
IDataErrorInfo - not seeing any error message even though one gets picked up
Silverlight IDataErrorInfo message does not show in custom control's textbox
I'm using the Telerik RadComboBox in similar fashion and I have no issues getting the error message displayed. Here's my XAML for your reference, hope this helps...
<TextBlock Text="Select a User to Assign the Current Step To:" Grid.Row="3" Visibility="{Binding ShowAssigneeUser}"/>
<telerik:RadComboBox x:Name="cmbAllActiveCrmUsers"
IsEditable="True"
Grid.Row="4"
telerik:TextSearch.TextPath="FullName"
Text="{Binding FullName, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
VerticalAlignment="Center"
Visibility="{Binding ShowAssigneeUser}"
ItemsSource="{Binding AllActiveCrmUsersExceptCurrentUser}"
SelectedIndex="{Binding DefaultAssigneeUserIndex, Mode=TwoWay}"
ItemTemplate="{StaticResource ComboBoxMultilineTemplate}"
Style="{StaticResource ComboBoxStyle}"
Command="{Binding AssignUserChangeCommand}"
CommandParameter="{Binding SelectedIndex, ElementName=cmbAllActiveCrmUsers}"
>
<telerik:RadComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</telerik:RadComboBox.ItemsPanel>
</telerik:RadComboBox>

ComboBox SelectedItem binding not updating

I'm a bit puzzled:
this works:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Rol" />
<ComboBox ItemTemplate="{StaticResource listRollen}"
Height="23" Width="150"
SelectedItem="{Binding Path=SelectedRol, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=allRollen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
and the property for SelectedRol is:
public TblRollen SelectedRol
{
get { return _selectedRol; }
set
{
if (_selectedRol != value)
{
_selectedRol = value;
OnPropertyChanged("SelectedRol");
}
}
}
But this doesn't work:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Soort" />
<ComboBox ItemTemplate="{StaticResource listSoorten}"
Height="23" Width="150"
ItemsSource="{Binding Path=allSoorten}"
SelectedItem="{Binding Path=SelectedProduct, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
with following property SelectedProduct:
public TblProduktSoorten SelectedProduct
{
get { return _selectedPSoort; }
set
{
if (_selectedPSoort != value)
{
_selectedPSoort = value;
OnPropertyChanged("SelectedProduct");
}
}
}
somewhere in my code I set SelectedProduct = p.TblProduktSoorten and while debugging, I see the property gets set correctly...
Combobox inside a DataGrid?
If the combobox is in a DataGrid you must add this :
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
See this : https://stackoverflow.com/a/5669426/16940
Try to use not selected item but value path look at the code sample
<ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
SelectedValuePath="Name" SelectedIndex="0" Grid.Row="1" Visibility="Visible" Canvas.Left="10" Canvas.Top="24" Margin="11,6,13,10">
</ComboBox>
the binding property is
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
projects = value;
RaisePropertyChanged("Projects");
}
}
This might be related to the fact that apparently attribute order does matter, in your second case the ItemsSource and SelectedItem declarations are swapped.
If you set the SelectedProduct property when SelectedProduct is changed in the property changed event handler, you need to set this property asynchronously.
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProduct")
App.Current.Dispatcher.InvokeAsync(() => SelectedProduct = somevalue);
}
My problem was caused by my own tired brain. Same symptom, maybe it will kick you into seeing your problem.
Setting the SelectedItem must be given an item in the List!! (duhh) Normally this happens naturally but I had a case I got a "Role" from another service (Same object type) and was trying to set it and expecting the combobox to change! ;(
instead of -
Roles = roles;
CurrentRole = role;
remember to do this -
Roles = roles;
CurrentRole = roles.FirstOrDefault(e=> e.ID == role.ID); //(System.Linq)
I don't know if you fixed it yet, but I encountered the same issue today.
It was fixed by making sure the collection for selecteditems was an ObservableCollection.
I think this problem is caused by the type of ItemSource and SelectedItem is mitchmatched.
For example, if the ItemSource is binded to a List of int and the SelectedItem is binded to a string. If you set selected item to null or empty string, the combobox cannot know what item is selected. So the combobox will show nothing.
This might be old but I have not seen the trick that did it for me; I had to add NotifyOnSourceupdate=true to my SelectedItem in the ComboBox
This had me stumped for a while inside a DataGrid, using SelectedItem. Everything was fine but I am deserializing the app state which loads the items and also has a selected item. The collection was there but the selected isn't actually visible until I used the Text="{Binding Path=Score.SelectedResult.Offset}"
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ToolTip="Score offset results"
ItemsSource="{Binding Score.SearchResults,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Score.SelectedResult, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=Score.SelectedResult.Offset}"
SelectedValuePath="Offset"
DisplayMemberPath="Offset"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Categories