Xamarin Forms Picker SelectedItem Binding - xamarin.forms

The Xamarin Forms doc Xamarin.Forms.Picker.SelectedItem says there is a public property SelectedItem for Picker. However, I get an error when I try to bind to it. The picker is not very useful if you have to manually handle the SelectedIndex property.
Tony

No need to manually handle the SelectedIndex. You can use the Picker's SelectedItem property. Just make sure your types are the same. For example, if your ItemsSource is bound to a property:
BookTitles List<string> { get; set; }
your SelectedItem has to be something like:
SelectedBookTitle string { get; set; }
Make sure to set the SelectedBookTitle value to show a title when the page is first shown.
Do not forget to set Mode to TwoWay on the SelectedItem Binding.
for example:
<Picker ItemsSource="{Binding BookTitles}" SelectedItem="{Binding
SelectedBookTitle, Mode=TwoWay}" />
This will ensure the title is shown when the page is first displayed,
and keeps the value of SelectedBookTitle equal on the Page and codebehind/viewmodel.
No need to use behaviours in this example.

You can add this feature relatively easy, even with older versions of Forms pre 2.3.4 which supports it out of the box. Just create a custom behaviour to bind the picker items. You can implement your own version or use an existing library, like the Xamarin University Infrastructure Library which is available as source and as a Nuget
The detailed documentation shows how to use it:
<Picker ...>
<Picker.Behaviors>
<inf:PickerBindBehavior Items="{Binding Colors}"
SelectedItem="{Binding FavoriteColor}" />
</Picker.Behaviors>
</Picker>
The approach of the behaviour is to expose a bindable property (the items) and use an observable collection. Whenever that changes, the behaviour updates the items of the picker.

Related

xaml viewmodel declaration in prism

I am using PRISM with xamarin forms, and I like to declare my viewmodels in the XAML,
xmlns:local="clr-namespace:MyProyect.ViewModels"
……
<ContentPage.BindingContext>
<local:RegistroPageViewModel />
</ContentPage.BindingContext>
so I can have XAML intellicense, in this sample my RegistroPageViewModel constructor have one parameter beacause it need for the base class but I don't know how to pass it within the xaml
public class RegistroPageViewModel : ViewModelBase
{
public RegistroPageViewModel(INavigationService navigationService):base(navigationService)
{
registro = new RegistroInfo();
Title = "Perfil de usuario";
}
My specific question is: How can I still using XAML viemodels's declaration if the viewmodel have a parameter ? how can I pass a parameter in the XAML declaration?
thnaks in advance
For XAML to know about ViewModel, enable XamlC and Compiled Bindings. Documentation provides how to enable and use them properly.
XamlC checks for general compile time errors like property names and open-closing matching tags etc...
Compiled Bindings checks for existence of any property that is bound
You can use the view model locator (ViewModelLocator.AutowireViewModel="True") to have the view model created for you with all dependencies automatically injected.
Setting the view model as design data context (d:DataContext={d:DesignInstance local:RegistroPageViewModel}) should give you intellisense.

Adding item to collection does not refresh activity designer

Am re-hosting my designer and have added a toolbox item which has a WorkflowItemsPresenter to render multiple child activity items. So my model item has a collection as:
Sequence _innerSequence = new Sequence();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Browsable(false)]
[Description("")]
public Collection<Activity> Activities { get { return _innerSequence.Activities; } }
and the binding is
<sap:WorkflowItemsPresenter Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Items="{Binding Path=ModelItem.Activities}" VerticalAlignment="Center" HorizontalAlignment="Center" HintText="Drop activities here">
<sap:WorkflowItemsPresenter.SpacerTemplate>
<DataTemplate>
<Label HorizontalAlignment="Center" Height="21"/>
</DataTemplate>
</sap:WorkflowItemsPresenter.SpacerTemplate>
</sap:WorkflowItemsPresenter>
The binding works absolutely fine when the designer is loaded. Now i want to clear and add new items to this collection when some filter is updated on the designer. So in the set accessor of this filter property i call a method which does the following:
private void RefreshApplication()
{
Activities.Clear();
Activities.Add(new AddXYZApplication() { ApplicationName = "Test" });
}
Though the collection gets updated the designer does not refresh. I know there is a way of doing this by writing some designer code-behind (i.e. updating the collection via the model item tree), but I would ideally like to have NO code-behind and expect it work like any other WPF application.
Any help would be greatly appreciated as I have been trying to devise a way (using multi-binding, using eventing etc) from sometime now.
Cheerio,
V
Just to answer after my comment.
When you're editing through WorkflowDesigner you haven't an Activity per se. What you have is a ModelItem.
From the moment you load an activity to the designer, through WorkflowDesigner.Load(activity) you don't have an activity anymore, you just start editing a ModelItem.
You can access XAML through WorkflowDesigner.Text (after flush it) and do whatever you want with it. For example load it into an ActivityBuilder or WorkflowService but that is it.
Designers don't known, and never will, that activities have Collection<Activities>, Collection<Variable> or any other properties. They only know the ModelItem and the properties it has, period.
In resume: changes have to be made to ModelItem because it's what designers bind to.

mvvm-light: Normal Property or DependencyProperty

In mvvm-light, it comes with two property-creation snippets: mvvminpc to create a 'normal' property; and mvvmpropa to create an attached property (aka dependency property). I just want to know if there is any guidance on what to take into consideration when choosing which one to use?
I've been also searching for a while on these property topics for MVVM light. Below is my understanding of the property snippets provided in MVVM light. There aren't really any cases where you would use one over the other because they are for different purposes.
Bindable Property - Bindable properties are created in your ViewModels to expose data which your view will display.
Examples include: Displaying a collection of Employees, or the selected employee information.
Dependency Property - View specific when it comes to the code snippet. These properties can be set to a constant value or use data binding for changes depending on the viewmodel data.
Examples include: A textblock control's "Text" property is a dependency property. The "Height" and "Width" properties are also dependency properties.
Attach Property - Also used more specifically for user controls. This property is added to a parent control. Child controls use these properties to behave a certain way within the parent control.
Example includes: a Dockpanel has a "Dock" (Attached Property Name) that isn't used by the Dockpanel itself. It is used by the children contained inside of it, the children will now be able to set the property: DockPanel.Dock="Top".
<DockPanel>
<TextBlock Text="{Binding EmployeeName}" DockPanel.Dock="Top" />
<Button Content="Click Here" DockPanel.Dock="Bottom" />
</DockPanel>
In the example code above:
The Bindable Property is the EmployeeName, which would be a public property in the viewmodel code.
The Dependency Property is the Text="" property of the textblock and the Content="" property of the button.
The Attach Property is the DockPanel.Dock property used in the Textblock and button, but is actually exposed by the Dockpanel itself. Notice that the Dockpanel doesn't contain any of the .Dock code, only the children do.
Dependency properties are recommended when you create UI components (controls, etc.): they have better time performances for binding.
Normal properties are used if you have business object or if you dont have/create UI controls.

stackpanel visibility editing in silverlight

I am working on silverlight web application (RIA) hosted on to a silverlight web application.
Background: I have a stackpanel in one of the xaml pages. I tried to simplify my problem. It is down as follows:
My xaml page has a stack panel and that stackpanel has only textblock and button in it. only authorized users can see the value in the textblock, when navigated to the xaml page. If the user is unauthorized, I am planning to show "unauthorised" message (instead of value) in the textblock (button is also collapsed. I dont show button.)
FYI, this value of texblock comes from a WCF service and i have made proper attributes for authorization in the service. If unauthorized, value will not come to textblock from service. What I am doing now, is just for UI, when some user tries to enter the url of the page from browser's address bar I want to show him the unauthorised message.
What have I done so far:: I gave a name to stackpanel. I gave a name to textblock and a name to button. if authorized, I am setting the text value of text block to the service returned value.
If unauthorized, I am changing the visibility and text from .cs file as this.
textblock.Text="unauthorized";
buttonname.Visibility = Visibility.Collapsed;
Problem: Problem is I got an idea. :( When I have a name for my stackpanel, I can say
stackpanelname.Visibility = Visibility.Collapsed;
But I cannot show my message (Textblock) now, coz child controls are also collapsed with parent. Is there any way that, I can collapse my stackpanel (parent control), but only one control of it (one child control, or few) is visible.
Solutions: As I am typing this, I got a solution, I can go for a new stack panel, with a text block, whose visibility I can set to VISIBLE and text as my message. But, is it the only way.? How do we handle these situations?
In general, presuming my question is clear, what is general approach to provide security in this kind of scenarios, from UI. Is it gonna be redirecting to error page/login page or a message to user on the same page or any other thing. Presuming, Backend services, will be having attributes and logic for authorizations.
Normally I would solve such an issue with bindings. I'm not sure if you're willing to take that approach, but given that you are. For example, i would do this:
<TextBlock Text="{Binding AuthorizationCaption,FallbackValue='Unauthorized'" />
The fallback value here is used to see what it looks like for design purposes. FallbackValues only get presented when a binding fails.
For the button, I would do this:
<Button Content="My Button" Visibility="{Binding IsAuthorized,Converter={StaticResource VisibilityValueConverter},FallbackValue=Collapsed}" />
In the above example, you will notice that I used what I called a VisibilityValueConverter. This of course would be a part of my resources that I define right about "LayoutRoot" in the XAML. e.g.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyUICustomizationLib;component/rdMyResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
My VisibilityValueConverter is a simple converter to convert a boolean value to a visibility attribute. It's pretty reusable. It implements IValueConverter which I think is in System.Windows.Data. Along the lines:
public class TVisibilityValueConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool _visibility = (bool)value;
return _visibility ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility _visibility = (Visibility)value;
return _visibility == Visibility.Visible;
}
}
I would embed my value converter in my ResourceDictionary by , first, defining a namespace to it's location -
xmlns:muicl="clr-namespace:MyUICustomizationLib.ValueConverters"
Then defining the static resource:
<muicl:TVisibilityValueConverter x:Key="VisibilityValueConverter" />
Last, but not least, Implement my viewmodel properties and commands to fit what has to be. i.e, I make the neccesary server calls, and on the call backs, i toggle the AuthorizationCaption property and the IsAuthorized property accordingly. The smmoothest way would be to let the AuthorizationCaption be a simple if statement that depends on the IsAuthorized property. Let the set method of the IsAuthorizedProperty raise an event notification that the AuthorizationCaption changed too. e.g.
set
{
__fIsAuthorized = value;//set private member
this.RaisePropertyChanged("IsAuthorized");
this.RaisePropertyChanged("AuthorizationCaption");
}
Of course they may be more to set up on your end. But this would be the route I would take.

How do I get a bound control to report "Empty" when it is bound to emptiness?

I'm trying to extend the RSS reader example from here.
I've converted the app to panorama. I've made it so that the first panorama item loads with my feeds, and the second item has categories with corresponding checkboxes. The categories are databound to a Categories class, which gets populated from an XML file.
Anyway, the 'my feeds' section which has code that looks like this:
<TextBlock x:Name="ItemName" Text="{Binding ItemTitle}" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="ItemDetails" Text="{Binding ItemDetails}" Style="{StaticResource PhoneTextSubtleStyle}"/>
and I'm trying to get it to display "Empty" when there are no feeds in the list (feeds are populated when the checkboxes in the adjacent panel are checked). So I added this code to my OnNavigatedTo method in MainPage.xaml.cs
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
this.DataContext = App.Model;
base.OnNavigatedTo(e);
// If there are no feeds yet, let the user know
if (App.Model.FeedItems.Count == 0)
{
App.Model.FeedItems.Add(
new ViewModel.ItemModel()
{
ItemDetails = "",
ItemTitle = "Empty!",
ItemLink = "#"
}
);
}
}
but that wasn't the right approach. Now if I navigate to another page and come back and there were feeditems in the list, I still get "Empty" followed by the items. How do I fix this?
Also, when the "Empty!" actually works, I am still able to click on the link (ItemLink above); how do I disable the click event for this one case?
In a bit of a coincidence I posted last night about how to extend the ListBox control to have an empty data template. It should be easily extended to something like Panorama or Pivot controls.
The basic theory is that you have a content control with your "No items text" and control the visibility of it and the ListBox depending on whether the ListBox has items.
You can read it at Extending the WP7 ListBox.
In addition to Nigel's extended ListBox, you have at least a couple of possible solutions:
Create a UserControl embedding your ListBox plus a TextBlock showing the "Empty" text, and make that UserControl toggle the visibility of the ListBox or TextBlock depending on the content of the feeds list.
Replace your ListBox with a LongListSelector from the Silverlight Toolkit and set that LongListSelector's ListHeader property to show the "Empty" text when the feeds list is empty.

Resources