Comments (8)
I haven't used this library directly, but looked at parts of it as inspiration to roll my own. Looking at the source code and unit tests for this library, I'm pretty sure you need to call SetProperty in your property setters to get them to broadcast a PropertyChanged event that would trigger your handler that calls the RaiseCanExecuteChanged method. Also, does your Airport class also implement BaseViewModel/INotifyPropertyChanged? The Airport.name property (or is it just a field?) would need to emit a PropertyChanged event as well, and I think you'd have to set-up/tear-down a weak-event-listener to listen for the SelectedItem.name change as the SelectedItem changes.
Instead, I might suggest wrapping the SelectedItem.name in a SelectedItemName property to make the event handling easier:
private Airport? _selectedItem;
public Airport? SelectedItem
{
get => _selectedItem;
set
{
SetProperty(ref _selectedItem, value);
// Broadcast that the SelectedItemName should now have a new value as well.
OnPropertyChanged(nameof(SelectedItemName);
// Broadcast that the command's CanExecute should be re-evaluated now.
MyProperty.RaiseCanExecuteChanged();
}
}
SelectedItemName // Bind this to your TextBox.Text instead
{
get => SelectedItem?.name ?? string.Empty;
set
{
if (null == SelectedItem)
{
// Can't set the value if no item is selected.
// Broadcast the changed event to refresh the binding (will be empty string).
// This effectively rejects typing in the box until an item is selected.
OnPropertyChanged();
return;
}
SetProperty(ref SelectedItem.name, value); // Note: this may only work if Airport.name is a field, not a property.
/* If Airport.name is a property, do this instead:
SelectedItem.name = value;
OnPropertyChanged(); // Broadcast that this property (SelectedItemName) has a new value.
*/
// Broadcast that the command's CanExecute should be re-evaluated now.
MyProperty.RaiseCanExecuteChanged();
}
This way you can drop the anonymous PropertyChanged event delegate from your constructor altogether.
Also, you probably don't need the public setters for your MyProperty
, Services
, or AirportsList
properties - typically nothing outside of this class should probably be setting those.
You might want to add UpdateSourceTrigger=PropertyChanged
to your TextBox.Text binding as well so it updates as you type instead of the default behavior of only updating after the focus changes (unless that's the behavior you want).
Hope this helps, and if it's still having an issue, maybe there really is an issue with the library. Although I suspect this should address your problem.
from mvvm-helpers.
Thanks, @nedmech, I have a question, if I am using fody to inject my property change, Do I still need
private Airport? _selectedItem;
public Airport? SelectedItem
{
get => _selectedItem;
set
{
SetProperty(ref _selectedItem, value);
// Broadcast that the SelectedItemName should now have a new value as well.
OnPropertyChanged(nameof(SelectedItemName);
// Broadcast that the command's CanExecute should be re-evaluated now.
MyProperty.RaiseCanExecuteChanged();
}
}
As far as I know, when you add fody and put in your class [addNotifyPropertyChangeInterface] it will add all that code for you you only need to do is
public Airport SelectedItem { get; set }
Also my class has the [AdNotyfyProertyChangeAtribute] courtesy of fody
from mvvm-helpers.
I haven't used fody before, so I'm not familiar with the usage. A quick peek at it seems like you're probably correct - it should be auto-generating the code for notifying that the selected item has changed. Although there's still the question of whether or not the Airport.name is a field or property and if the Airport class implements INotifyPropertyChanged. Even if your Airport.name is a notifying property, there's still a missing connection between the SelectedItem.name changing and triggering the RaiseCanExecuteChanged. Without a weak-event-listener or wrapping it in another property, there's nothing in your MainWindowViewModel that is listening for change notifications from the Airport.name value.
Try it with just the SelectedItemName property wrapper and see what happens. My guess is that typing in a name will trigger the CanExecute update, but just selecting an item won't. Maybe some combination of my idea and your original code where you subscribed to the PropertyChanged event will work since you should get the PropertyChanged event when the SelectedItem changes and when the SelectedItemName is updated. You can probably exclude the RaiseCanExecuteChanged from the SelectedItemName setter in this case.
from mvvm-helpers.
I did it, but there is a small issue
the button only enables, when I press the tab, to make it loses focus, what I want to do is that when I type the button enables infinitely, without me having to change the control focus or anything like that.
I just my code in GitHub, if you want to check it out or modify it or whatever
https://github.com/eduardoagr/Travel
By the way, this library in combination with fody is extraordinary
from mvvm-helpers.
To get the changes to register immediately when typing in the TextBox, you need to add the UpdateSourceTrigger attribute I mentioned before to the TextBox.Text binding:
<TextBox Grid.Column="1" Text="{Binding Path=SelectedItem.name, UpdateSourceTrigger=PropertyChanged}"/>
This should cause the PropertyChanged event for the name property to fire with every keystroke.
Does the button enabled when you select an Airport item that already has a name? You may still need to add a RaiseCanExectuteChanged to the setter for the SelectedItem, or another PropertyChanged event delegate to handle refreshing the CanExecute status on selection change.
In your constructor, I think you've got a problem with the OnAnyPropertiesChanged action assignment:
SelectedItem = new Airport
{
OnAnyPropertiesChanged = () => { MyProperty?.RaiseCanExecuteChanged(); }
};
I think this will only attach to the new instance of Airport that gets created in the constructor. If you've got your AirportList and SelectedItem bound to a selectable control (ListBox, ListView, ComboBox, etc.) when you actually select a new Airport from your collection, the SelectedItem will be replaced by the selection, and that newly selected item doesn't look like it will have the OnAnyPropertiesChanged action assigned. It doesn't look like your code is completed to that point yet, but just something to be aware of.
But it sounds like you're on the right track and that there's not an issue with the library, just some tweaks needed to your implementation.
from mvvm-helpers.
I changed my code, but I still cannot manage to enable it as I type
from mvvm-helpers.
It looks like you added the UpdateSourceTrigger attribute to the Button.Command binding. It belongs on the TextBox.Text binding.
from mvvm-helpers.
lol, thanks so much
from mvvm-helpers.
Related Issues (20)
- .net core 3.0 end of life HOT 2
- Is there any documentation? HOT 3
- Update from 1.5.0-beta to 1.6.2 on SafeFireAndForgetAsync HOT 1
- RaiseCanExecuteChanged not included in IAsyncCommand HOT 3
- When using ObservableRangeCollection.AddRange with IEnumerable, CollectionChanged event may be corrupt
- Index out of range exception when calling ReplaceRange on an ObservableRangeCollection HOT 2
- ObservableObject.PropertyChanged event is not weak HOT 1
- null reference on observable object string property HOT 1
- WPF HOT 1
- ObservableRangeCollection.Remove doesnt update UI (PropertyChange)
- Android.OS.NetworkOnMainThreadException: '' on RefreshCommand
- ReplaceRange does not update the ui HOT 2
- ReplaceRange not update ui HOT 1
- Using Command CanExecute HOT 2
- WPF issue -> no disabling of buttons using MvvmHelper commands HOT 2
- On wpf, Implementing Icommand, it will create for us the methods of canExecute and will Execute HOT 1
- Strange Error... ObservableCollection with IGrouping on IOS (Development with Visual Studio Windows)
- Explanatory Video not found 404 HOT 1
- Strong Assembly name for MVVM - helpers HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mvvm-helpers.