Using MvvmCross, how do I get an "opposite" binding for a bool? - mvvmcross

In my particular application, I would like the background to be Transparent, i.e., Transparent = true, when the IsSelected is false. I suspect I have to write a Converter, but perhaps there is an easier way?
set.Bind(selectedBox).For(v => v.Transparent).To(vm => vm.IsSelected).OneWay();
Looks like there is a WithConversion<...> possibility. Perhaps I need a NotValueConverter? Hard to believe this is not already implemented somewhere....
Update. I added the following to my Core
public class NotConverter : MvxValueConverter<bool, bool>
{
protected override bool Convert(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !value;
}
protected override bool ConvertBack(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !value;
}
}
but it does not seem to be picked up by the sweep and
set.Bind(selectedBox).For(v => v.Transparent).To(vm => vm.IsSelected).WithConversion("Not").OneWay();
does not make any difference.

Converters need to end with ValueConverter to be picked up automatically by MvvmCross. You can also use a generic type to use WithConversion.
set.Bind(selectedBox).For(v => v.Transparent).To(vm => vm.IsSelected).WithConversion<NotConverter>().OneWay();
I thought that "Not" was a built-in converter, and i've used it on Android, but i can't find anything on this so far.

I was curious about this, so I started looking through the MvvmCross code. On Android, you can do something like:
app:MvxBind="Enabled !SomeBoolean"
which works, but it's actually the MvxInvertedValueCombiner that's doing this, not any ValueConverter. So in fluent form this should do the trick:
set.Bind(selectedBox).For(v => v.Transparent).ByCombining(new MvxInvertedValueCombiner(), vm => vm.IsSelected)
I've actually never used it in that way, but it seems to work. Furthermore it appears that the value combiner is applied before any value converter, so let's say you were tired of that MvxInvertedVisibilityValueConverter, you could do something like this on Android:
app:MvxBind="Visibility Visibility(!HideMe)"

Related

Caliburn.Micro cannot bind to LongListSelector

Windows phone 8 with Caliburn.Micro 2.0.1 cannot bind to LongListSelector. For Caliburn tries to bind items to Visibility property.
Here is XAML
<phone:LongListSelector
x:Name="Items"
ItemTemplate="{StaticResource MyItemTemplate}">
</phone:LongListSelector>
and view model property is pretty basic:
IObservableCollection<Item> _Items;
public IObservableCollection<Item> Items
{
get { return _Items; }
set
{
_Items = value;
NotifyOfPropertyChange(() => Items);
}
}
public class Item : PropertyChangedBase
{
string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; NotifyOfPropertyChange(() => Name); }
}
}
Here is the debug output
System.Windows.Data Error: 'MS.Internal.Data.DynamicValueConverter' converter failed to convert value 'Caliburn.Micro.BindableCollection`1[Checklists.ViewModels.ItemsPageViewModel+Item]' (type 'Caliburn.Micro.BindableCollection`1[CLS.ViewModels.ItemsPageViewModel+Item]'); BindingExpression: Path='Items' DataItem='CLS.ViewModels.ItemsPageViewModel' (HashCode=38524289); target element is 'Microsoft.Phone.Controls.LongListSelector' (Name='Items'); target property is 'Visibility' (type 'System.Windows.Visibility').. System.InvalidOperationException: Can't convert type Caliburn.Micro.BindableCollection`1[CLS.ViewModels.ItemsPageViewModel+Item] to type System.Windows.Visibility.
at MS.Internal.Data.DefaultValueConverter.Create(Type sourceType, Type targetType, Boolean targetToSource)
at MS.Internal.Data.DynamicValueConverter.EnsureConverter(Type sourceType, Type targetType)
at MS.Internal.Data.DynamicValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertToTarget(Object value).
The convention you're trying to make use of here is the one Caliburn.Micro has set up for ItemsControl, unfortunately it doesn't appear that LongListSelector inherits from ItemsControl. It's odd that it doesn't so you'd assume everything would just work.
A very basic convention for LongListSelector could be added with the following
ConventionManager.AddElementConvention<LongListSelector>(LongListSelector.ItemsSourceProperty, "DataContext", "Loaded");
which would be called in your Bootstrapper. Note that this convention does't set up a default ItemTemplate that the one for ItemsSource does.
Edit:
The first property is used for property binding conventions, if you have a property matching the x:Name then this is the property bound to.
The second is the parameter property, if you refer to the element as a parameter in a message such as cm:Message.Attach="DoStuff(Items)" then what property is used.
The third is event that fires the action if there is one attached.
The one mentioned in the comments
ConventionManager.AddElementConvention<LongListSelector>(LongListSelector.Items‌​SourceProperty, "SelectedItem", "SelectionChanged");
is better in that if you're using any of the other features that require the second two properties. The first convention simply uses boiler plate parameters.
which makes sense its not a bug since LongListSelector isn't in the ConventionManager list of controls for windows Phone. You would have to add it as a custom convention for that control. Otherwise just bind normally...

Is there a way to bind a Dictionary in mvvmcross

I started using observable ConcurrentDictionary because it's threadsafe. But now I face a problem how to bind it to the list.
local:MvxBind="ItemsSource SourceDictionary"
obviously cannot work because item consists of the KeyValuePair and not the object itself.
local:MvxBind="ItemsSource SourceDictionary.Values"
does not work. Which, I must admit, puzzles me.
I even tried a long shot and did some converter :
public class SourceDictionaryValueConverter : MvxValueConverter<KeyValuePair<string, SourceClass >, SourceClass >
{
protected override SourceClass Convert(KeyValuePair<string, SourceClass> value, Type targetType, object parameter, CultureInfo culture)
{
return value.Value;
}
}
and bind it like this
local:MvxBind="ItemsSource SourceDictionary, Converter=SourceDictionary"
but it didn't work. I suppose it asks for IList.
Is there any way to bind ListView to the Dictionary?
You should be able to bind to a Dictionary - or indeed to any IEnumerable.
If you are binding to the Dictionary itself (rather than to Values) then you will need to write your item bindings so that they know about KeyValuePair - e.g. so you might need to bind to Key.Name rather than to just Name.
However, Dictionary's themselves do not notify listeners of changes - so using a Dictionary is like using a List - not like using an ObservableCollection. If you want this type of behaviour then you will need to write or find a Dictionary class which implements INotifyCollectionChanged.

Is it acceptable to return null from a factory constructor in Dart?

I've been writing some code in Dart. I really love the factory constructor, but I'm afraid that I'm abusing it's usefulness. In particular, when I write a value object class, I sometimes return null if the validation fails.
class EmailAddress {
static final RegExp _regex = new RegExp(...);
final String _value;
factory EmailAddress(String input) {
return _regex.hasMatch(input) ? new EmailAddress._internal(input) : null;
}
const EmailAddress._internal(this._value);
toString() => _value;
}
At first, this doesn't seem all that bad. However, when you actually use it, this is what you see.
methodThatCreatesAnEmailAddress() {
var emailAddress = new EmailAddress("definitely not an email address");
...
}
The argument why this is bad is that a developer coming from another statically typed language, such as Java or C++, would expect emailAddress to always be initialized to a non-null value. The argument why this is perfectly acceptable is that the constructor is factory and, as such, is allowed to return a null value.
So is this bad practice or taking advantage of a useful feature?
With null-safe Dart, factory constructors are no longer permitted to return null.
Existing factory constructors that return null are expected to be replaced with static methods when migrated.
Returning null value as result from a factory is acceptable because the builtin factory feature in Dart Factory software concept does not have any null-restriction.
On the other hand I can rephrase your question "Is it acceptable to return null from a equality operator"
bool operator ==(other) {
return null;
}
This is also acceptable because there is no such restriction that this operator cannot return the null value.
But there is another question? Why do it and how to avoid it?
factory EmailAddress(String input) {
return _regex.hasMatch(input) ? new EmailAddress._internal(input) :
throw "something went wrong";
}
P.S.
My personal opinion that returning null from factory in Dart is a bad practice because factories in Dart are very difficult to distinguish from constructors.
From the outside they looks like constructors with the difference that they are more powerful because can construct different kinds of objects.
And they also have their restrictions but this is another story.
I'm going to dissent from other answers: at least for named factory constructors, I don't see anything wrong with returning null.
The main differences between a factory constructor and a static method are that a factory constructor can be used with new and can be the unnamed, default constructor. Using new is now discouraged, so a named factory constructor in most cases is not distinguishable from a static method invocation at a callsite.
I don't see anything wrong with a static method returning null, and therefore I don't see anything wrong with a named factory constructor returning null either.
If the factory constructor is unnamed, then I would agree that returning null is likely to be unexpected by the caller and probably should be avoided.
That said, in such cases, there isn't much reason to use a factory constructor over a static method, and a static method is clearer.
Update
Using a static method to return null is the recommendation for code migrated to null-safety. See my new answer.
It's bad practice. When someone calls a constructor they expect a non-null value.
For your case I might do validation in a static method:
class EmailAddress {
final String _value;
static final RegExp _regex = new RegExp(r"...");
static bool isValid(String email) => _regex.hasMatch(email);
EmailAddress(this._value) {
if (!isValid(_value)) throw "Invalid email: $_value";
}
}
Now you get code reuse and nice semantics. For instance:
querySelector("#sendButton").disabled = !EmailAddress.isValid(userEmail);
Please don't do this. As a user of a constructor I expect to receive an instance of the constructor's class. It's ok to return a pre-existing instance or an instance of a subtype in Dart, but don't return null.
I'd recommend one of two options to do what you want here:
throw an exception on invalid inputs. This way at least the error is early, rather than later if you've stored the null somewhere.
Use a static method instead of a constructor. Static methods can return null and not be as confusing.
Provide a fallback path, such as int.parse does. You can accept a callback that will be called on an error.
I prefer 1 or 3 myself. I'd like to know explicitly when something isn't valid.

Return an unset value in value converter

Using a value converter in WPF, you can return something like DependecyProperty.UnsetValue or Binding.DoNothing as special values to say leave the binding alone. Is there a similar mechanism in MVVMCross?
To be more specific about what I'm trying to do, is I have a view model property that is a three-state enum that I need to bind to 3 binary controls. So I thought I could bind each of the controls to a MyEnum -> bool converter that will have a conversion parameter set to the value of the converter and in the Convert method it will return true if the MyEnum state is equal to the parameter and false otherwise. So far so good. But I want this binding to be two-way, so I need to convert back. My convert back works something like this:
protected override MyEnum ConvertBack(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter is MyEnum)
{
if (value)
{
return (MyEnum)parameter; // this is fine
}
else
{
return ???
}
}
return base.ConvertBack(value, targetType, parameter, culture);
}
Basically, what I want to be able to do is say, if the state of my control is true update the bound property on my view model to be the same as the parameter, if not, leave the view model property alone.
Maybe this is the problem with using the strongly typed value converters?
If anybody else encounters a similar problem, in addition to Stuart's suggestions, this is what I actually ended up doing.
In the View Model
private MyEnum _selectedValue = MyEnum.SomeValue;
public MyEnum ? SelectedValue
{
get
{
return _selectedTab;
}
set
{
if (value.HasValue)
{
_selectedTab = value.Value;
RaisePropertyChanged(() => SelectedTab);
}
}
}
Then in my converter (now a MvxValueConverter<MyEnum?, bool>):
protected override MyEnum? ConvertBack(bool value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter is MyEnum) // this is just a sanity check
{
if (value)
{
return (MyEnum)parameter;
}
else
{
return null
}
}
return base.ConvertBack(value, targetType, parameter, culture);
}
It's not a general solution, but it fits my immediate need.
Update: UnsetValue is now available in mvvmcross - so this answer is no longer required.
Binding.DoNothing, DependencyProperty.UnsetValue or equivalent are currently not implemented in the MvvmCross binding system, and I don't believe there are any feature or pull requests currently open on this.
I'm afraid I don't really understand your example - the 'conversion parameter set to the value of the converter' and the if (parameter is MyEnum) snippet rather threw me - as far as I know, the parameter in windows xaml binding is a constant so I don't quite understand this example. Sorry if I've misunderstood.
Regardless, some possible approaches that might be used to assist with getting this functionality up and running in your mvx app are:
You could throw an exception from the ValueConverter:
For the Convert direction, the binding FallbackValue is used if a ValueConverter fails (throws an exception)
For the ConvertBack direction, the binding does nothing if an exception is thrown (although this would unfortunately generate some trace "error" output each time)
You could implement a custom binding for your control - something which only fires change updates when the change is one you are interested in (some custom bindings are introduced in N=28 in http://mvvmcross.wordpress.com which creates bindings like BinaryEditFooTargetBinding.cs - it would be straight-forward to customise/filter the TargetOnMyCountChanged behaviour in that class)
You could implement a custom binary control - which only fires change updates when the change is one you are interested in (for various platforms, some custom controls are introduced in N=18 to N=20 in http://mvvmcross.wordpress.com)
You could implement ViewModel binary properties which mirror your View and map to your three state enum
You could use a ValueCombiner within the Tibet binding system - it should be relatively straight-forward to work out a combiner based on top of something like MvxSingleValueCombiner.cs
Alternatively/additionally, please do also consider raising a Feature and/or Pull Request for this 'do nothing' type of functionality to be included in the TryGetValue/SetValue methods in https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Bindings/SourceSteps/MvxSourceStep.cs#L66 - but obviously the timeline on that might be longer.

OOP Proper use of interfaces in AS3

I'm designing a framework and in the process I have come across an interesting but most likely basic problem. I have a base class called CoreEngine and two other classes that extend it: CoreEngine1 and CoreEngine2. I created an interface that each of these classes would implement to increase the flexibility of my project. However, I have a problem... The definition of my methods in the interface do not match the definition in each inherited class! Each class must implement the following method:
function get avatar():AvatarBase;
The problem is that CoreEngine1 and CoreEngine2 expect a different type of avatar:
CoreEngine1
function get avatar():AvatarScaling
CoreEngine2
function get avatar():AvatarPlatform
As you can see, the return type for avatar in CoreEngine1 and CoreEngine2 do NOT match the type as specified in the interface. I was hoping that since both AvatarScaling and AvatarPlatform inherit AvatarBase that I wouldn't have a problem compiling. However, this is not the case. According to Adobe's documentation, the types MUST match the interface. I am trying to follow one of the core concepts of object oriented programming to extend the flexibility of my framework: "Program to an interface rather than an implementation". The first thing that comes to my mind is that the return type of the accessor method should be of an interface type (Maybe I just answered my own question).
I'm certain this is a common problem others have run into before. Architecturally, what do you think is the best way to solve this problem? Thanks in advance!
Regards,
Will
This is a limitation of how interfaces work and are declared.
If there's inheritance that can happen with the return types, as you've described with AvatarBase and subclasses, then I think the right approach is to make the return type the lowest common denominator and just handle the resulting object on the other end. So, if you're dealing with a CoreEngine1 object, you know you can cast the result from AvatarBase to AvatarScaling. Alternately, if you don't know the object type that you are calling get avatar() on, then you can type check the returned value. The type check would then only be needed if you're looking to call a method that exists on AvatarScaling but not on AvatarBase. I don't think returning an interface type will buy you much in this case because the only things that interface can implement would be things that all forms of Avatar share, which wouldn't be any different than methods in AvatarBase.
Like HotN and Dinko mentioned, it would be best to allow get avatar() to return AvatarBase allways and then cast the returned object as the concrete subclass.
Using Dinko's example:
public /* abstract */ class CoreEngine
{
public /* abstract */ function get avatar():AvatarBase {}
}
public function CoreEngine1 extends CoreEngine
{
override public function get avatar():AvatarBase { return new AvatarScaling(); }
}
public function CoreEngine2 extends CoreEngine
{
override public function get avatar():AvatarBase { return new AvatarPlatform(); }
}
public /* abstract */ class AvatarBase {}
public class AvatarScaling extends AvatarBase
{
public function someAvatarScalingMethod():void {}
}
public class AvatarPlatform extends AvatarBase
{
public function someAvatarPlatformMethod():void {}
}
To use a method from AvatarScaling, cast the returned object:
var c1:CoreEngine1 = new CoreEngine1();
var avatarScaling:AvatarScaling = AvatarScaling(c1.avatar());
avatarScaling.someAvatarScalingMethod();
hth
I think you answered your own question... the return type would still be AvatarBase, you need to follow the signature that you specified in the interface... but you can technically return ANY descendent of AvatarBase in that function. So doing something like
return new AvatarScaling();
in CoreEngine1 would be perfectly acceptable.
Of course in your calling function you will get back an AvatarBase instance, and you will have to know what this is in order to cast to a specific subclass.
CoreEngine1 ce1 = new CoreEngine1();
AvatarScaling avatar = ce1.avatar() as AvatarScaling;