-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nullability Problems with Bind() calls #2467
Comments
! Is fine in this scenario since we aren't using the expression for member access. It's just to get around the compiler error. |
You will often use ! In Rx coding. Eg
|
Yeah, I ran into that problem as well. I've been able to get around it in my codebase with this extension:
Would make your code look like
|
That sort of goes to my point that if we know the |
Yeah. I've avoided that one just due to additional invocation with the Select. |
True, there's a little bite on the optimization. I think it could be added to the Rx codebase as a single operator, though. A more official |
I'll play around with the nullables view model binding and see if it makes sense at least. |
Popped open an issue in the official Rx repo just to see what they think. dotnet/reactive#1262 I'll be toying around with the bindings more myself to get some more insight, too. |
Just remember we need to support interfaced types so I think we are stuck with this |
#2468 Should solve the There still remains the problem that I wonder if we could add some extension methods to ReactiveUserControl: public IObservable<TResult> WhenVmValue<TViewModel, TResult>(this ReactiveUserControl<TViewModel> control, Expression<Func<TViewModel, TResult>> property1)
{
if (control.ViewModel == null)
{
return Observable.Empty<TResult>();
// Or throw?
// Again, the idea would be to take the burden off the user of trying to figure out what to do when the view model
// is null, and internalizing that problem here and solving it once internally.
}
return control.ViewModel.WhenAnyValue(property1);
} Then the end users could do this again: this.WhenActivated(disposable =>
{
this.WhenVmValue(x => x.RunAllCommand)
.BindTo(this, view => view.RunButton.Command)
.DisposeWith(disposable);
} I wish it was as simple as encouraging users to do a simple if check: this.WhenActivated(disposable =>
{
if (this.ViewModel == null) return;
this.WhenAnyValue(x => x.ViewModel.RunAllCommand)
.BindTo(this, view => view.RunButton.Command)
.DisposeWith(disposable);
} But the expressions seem to remain unhappy. Presumably because an expression can theoretically be "applied" later on at a time when ViewModel is null again. |
Hmm might be worth opening a new issue with the WhenAnyValue ones and keeping this one about the Bind() based operators. |
can do |
In regards to the NotNull extension method, I do the same thing, except I replace the Select statement with a null-forgiving operator.
|
Was fixed with #2468 |
What about |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Describe the bug
Existing instructions on how to set up XAML code behind bindings have a few usability issues due to the new nullability compiler features being added.
Steps To Reproduce
Let's take a 101 binding example inspired from the RxUI docs (https://www.reactiveui.net/docs/handbook/data-binding/windows-presentation-foundation):
This should do the very simple job of binding a button's command to a viewmodel's command property.
Two problems come up with nullability.
viewModel
parameter is not null, while ReactiveUserControl's ViewModel member is. This means the user has to add the!
operator to get things to pass in, which is undesirable:It's my understanding that
!
should be avoided whenever possible, as it's bad coding habit that starts reintroducing routes for null ref errors into your code again.IReactiveBinding
object that is nullable. This doesn't hook intoDisposeWith
cleanly, as it expects a non null item. So now the user has to add?
checks after every bind call, which is not too clean:Since bindings like this are written -all- the time when developing a GUI, I think it would be good to set up the structure to not require any
!
usage, for sure, and then potentially try to avoid the need for elvis operators, if possible.Expected behavior
I would expect this code without any extra operators to function:
For me, my suggested solutions would be to make the
viewModel
parameter on OneWayBind nullable, so that it can take ReactiveControl's ViewModel property directly and cleanly. Since the bind definitions return potentially null bindings already, just have a null viewmodel short circuit and return a null binding, perhaps? Seems like the cleanest route.Second, since the binding calls are returning potentially null objects, it might be nice to upgrade
DisposeWith
to take nullable items, to remove the need for the?
call between the binding and the dispose every time.Perhaps the new class constraint isn't desirable and can be avoided, but this general idea is what I'm thinking.
The text was updated successfully, but these errors were encountered: