Disable Textbox based on CanExecute of command - wpf

I have a button and a Textbox, I've setup the button to a command using MVVM, INotifyPropertyChanged and MVVM.
However I want the Textbox to be disabled when the CanExecute method of the command returns false, i.e. I want the Textbox to be disabled when the button is disabled.
How do I hook a Textbox only to a command's CanExecute?

A TextBox doesn't have a Command property that you can bind directly to an ICommand source property.
Depending on the relationship between the TextBox and the Button in the view, you may bind the former's IsEnabled property to the second's:
<Button x:Name="btn" Content="..." Command="{Binding Command}" />
<TextBox IsEnabled="{Binding IsEnabled, ElementName=btn}" />
This only works if the controls belong to same namescope. If they don't, you should add a bool property to your view model and return the value of this one from the CanExecute method of the command, and also bind the IsEnabled property of the TextBox to it.

Related

Property resets when changing Usercontrols DependencyProperty

I've constructed a "Manager" of "Widgets" where i have a ListView/GridView with widgets.
The ListView binds the SelectedItem to a SelectedWidget property on the (Manager) ViewModel.
The SelectedWidget binds to a Usercontrol called WidgetConfig via a DependencyProperty called "Widget" where you can modify the properties of the selected Widget.
In the WidgetConfig , there are 2 RadioButtons:
<RadioButton GroupName="Lead" IsChecked="{Binding Widget.prop1, Mode=TwoWay, ElementName=root}" />
<RadioButton GroupName="Lead" IsChecked="{Binding Widget.prop2, Mode=TwoWay, ElementName=root}" />
When i select the 'prop2', the INPC signal is correctly sent and the model is updated accordingly. If then i click on the 'prop1', the INPC signal is sent + i get an additional signal from the prop2 radiobutton.
Here's the problem:
if i select prop2 and then select another Widget in the ListView. I get a INPC signal and prop2 has changed back to false!
what's going on ?
Some info:
The WidgetConfiguration is implemented using PostSharp NotifyPropertyChanged aspect.
The WidgetConfig UserControl is implemented by hand with DependencyProperty and INotifyPropertyChanged interface
EDIT:
I've created a reproducible example here : https://github.com/Montago/INCP-DP-BindingExample
What you have is a chain of two-way bindings, which are changing values on your Model:
Two-way binding between ListControl.SelectedItem(DP) and the ViewModel.SelectedModel(INPC).
Two-way binding between ViewModel.SelectedModel(INPC) and ModelControl.ActiveModel(DP).
Two-way binding between ModelControl.ActiveModel(DP) and Model.Prop1/Model.Prop2/Model.Name(INPC).
When you select First, Second and then again First, Second's prop2 is overwritten to false by WPF data binding.
A way to fix this is to remove the two-way binding that makes the overwrite of prop2, i.e. specify Mode=OneWay on RadioButton bindings.
My guess of what is happening: RadioButton's logic and two-way binding. When Second is selected in the list box and you change the selection to First, WPF's data binding sets Prop1 radio button as selected (because First.prop1 == true). At that point, the second radio button is still selected, so to respect the group principle, it needs to get unselected. However, there is still the two-way binding active on the Prop2 radio and thus Second.prop2 gets set to false.

Bind multiply Comboboxes to a TextBox

I've bound a ComboBox to my TextBox
<TextBlock Grid.Row="1" Name="DescriptionText" Text="{Binding ElementName=ScreenLocations, Path=SelectedItem.Description}" />
I have 4 ComboBoxes in my grid. What I want to do is, every time I select an item from any ComboBox, update the TextBox with the selected objects Description property.
Is it possible to bind multiple ComboBoxes to one TextBox, or would I need to use an event of some sort?
Create a property in your ViewModel and bind all your comboboxes' 'selectedItem' property to it (Use Mode="OneWayToSource", this will prevent changes on selectedItem of one ComboBox to affect the other), then bind your TextBox to the same property created in the VM with Mode="OneWay". Don't forget to implement INotifyPropertyChanged in your VM.

Binding to a datatemplate control WPF

I have a TabControl which binds an ObservableCollecion<T>. Every tab represents one object from OC. In the tab header i have a button:
<Button Command="{Binding DeleteCommand}">x</Button>
which should delete an object from the observable collection and consequently represent the result as the deleted tab. However the command is not acknowledged when i click on the x button, probably because it searches for a property in its model(?). Is there any way this would work?
You can bind to TabControl's DataContext using RelativeSource markup extension.
Also, in case you want to remove the item from ObservableCollection, pass the binding via CommandParameter which will be an instance of T (model object).
<Button Command="{Binding DataContext.TestCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=TabControl}}"
CommandParameter="{Binding}"/>

WPF bind a control visibility to the focused property of another control

I have a combobox that displays a list of items, and I want to place a button next to it which triggers a command to see the details of the selected item. So far, so good. Now I want the button to be visible only if the combobox has focus (or is in "edit" mode, but not only when the popup is open).
I thought I could bind the visibility of the button to some focus property of the combobox, something like this:
<Button Content="Details" Visibility="{Binding ElementName=elementListComboBox,
Path=IsFocused, Converter={StaticResource Bool2VisibilityConverter}}"/>
But I found no way to know if the control I want is focused or not. I looked at the FocusManager.FocusedElement, but I don't know how to get the focused control I want inside the binding. Is there a way to achieve this in XAML?
Ok, the way to get this working as I wanted is this:
<Button Command="{Binding SomeCommand}"
Content="Details"
Focusable="False"
Visibility="{Binding ElementName=elementListComboBox,
Path=IsKeyboardFocusWithin,
Converter={StaticResource Bool2VisibilityConverter}}"/>
Two key factors here: bind the button's visibility to IsKeyboardFocusWithin property of the combobox, and set the button's Focusable property to false, else it will get collapsed when you want to click on it.
Hope this is useful.

Disable button when datagrid is in edit mode

I have usercontrol with a DataGrid binded to an observablecollection of items and two buttons: save changes and discard changes.
My problem is that when the user is editing a datagridrow the buttons remain clickable but aren't executed.
Is there a way to disable the buttons when the DataGrid is in edit mode?
I tried this code with no success:
<Button Content="SaveChanges" Command="{Binding Path=CmdSaveChanges}"
IsEnabled="{Binding ElementName=MyDataGrid, Path=IsEditing, Converter={StaticResource InverseBooleanConverter}}" />
You are binding to an IsEditing property of an element named MyDataGrid which presumably is a DataGrid. However, DataGrid has no such property.
Although DataGridCell has an IsEditing property, there is no easy way to get the currently editing cell. DataGrid.CurrentCell will not give you the DataGridCell, but only a DataGridCellInfo.
You are perhaps better of with attaching handlers to the DataGrid's BeginningEdit and CellEditEnding events.

Resources