Use mvvm-light CustomEvent Trigger with ApplicationBarIconButton - windows-phone-7

The sample code below for a button will trigger opening of a second page.
<Button x:Name="btnSelect" Content="Select" HorizontalAlignment="Right" Margin="0,8,20,6"
Grid.Row="2" Width="200">
<Custom:Interaction.Triggers>
<Custom:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand x:Name="btnSelectClicked"
Command="{Binding SelectEventPageCommand, Mode=OneWay}"/>
</Custom:EventTrigger>
</Custom:Interaction.Triggers>
</Button>
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void ContentGrid_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
Messenger.Default.Register<GoToPageMessage>(this, (action) => ReceiveMessage(action));
}
private object ReceiveMessage(GoToPageMessage action)
{
StringBuilder sb = new StringBuilder("/Views/");
sb.Append(action.PageName);
sb.Append(".xaml");
NavigationService.Navigate(
new System.Uri(sb.ToString(),
System.UriKind.Relative));
return null;
}
}
http://galasoft.ch/mvvm/getstarted/
Can anyone suggest how I can do the same using an ApplicationBarIconButton? I get an error Property 'Triggers' is not attachable to elements of type ApplicationBarIconButton.
Or should I just use CodeBehind?
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1">
</shell:ApplicationBarIconButton>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Yeap ApplicationBar is a little bit different fom other controls in Silverlight. I was able to use an ICommand by using this one:
http://blog.humann.info/post/2010/08/27/How-to-have-binding-on-the-ApplicationBar.aspx
or the Silverlight toolkit which offers some extensions as stated in this answer:
How to add an application bar to a user control in wp7 but I never used it.

The ApplicationBar is a service that is provided by the operating system, i.e. not part of the Framework, and doesn't support Triggers as you have already discovered.As mentioned above there are a number of solutions that provide workarounds for this problem.
Alternatively, you could use the ApplicationBarButtonCommand and ApplicationBarButtonNavigation behaviors from the Silverlight Windows Phone Toolkit. It's a simple enough task to create your ApplicationBarMenuCommand if you need one. In your case, for using an ApplicationBar button to navigate to a page, then the ApplicationBarButtonNavigation behavior will do the trick.

Related

Xamarin Forms: System.ObjectDisposedException when setting Focus to an Entry control

I have the following Xamarin Forms page that throws an exception on this line...
The first time this page is loaded, the OnAppearing works fine, sets the focus properly, and doesn't throw an exception.
When I navigate back to this page (ie, logout), OnAppearing is throwing the following...
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Xamarin.Forms.Platform.Android.EntryRenderer'.
What is the best way to set focus to a control on a page in Xamarin Forms?
I'm not sure what is in your XAML, but if you define the x:Name="_entry" on the Entry in XAML, and use that name to access the control directly instead of FindByName, it should work fine.
I try to reproduce your issue at my side, but it works fine and there is no issue when I click Button to navigate another page and coming back. Please take a look my code:
<StackLayout>
<Label
HorizontalOptions="CenterAndExpand"
Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand" />
<Entry
x:Name="UserNameentry"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand" />
<Button
x:Name="btn1"
Clicked="btn1_Clicked"
HeightRequest="50"
HorizontalOptions="FillAndExpand"
Text="btn1"
VerticalOptions="CenterAndExpand"
WidthRequest="200" />
</StackLayout>
public Page4()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
var usernameentry = FindByName("UserNameentry") as Entry;
usernameentry.Focus();
}
private async void btn1_Clicked(object sender, EventArgs e)
{
Page3 page = new Page3();
await Navigation.PushModalAsync(page);
}
If you still have this issue, please provide some code about xaml here.

how to use radio buttons in xamarin forms

Creating a Registration page, I need to get the following data from user.
First Name
Last Name
Username
Email
Password
Date of Birth
Gender
User Role
For the last two parameters, I am unable to find how to use radio buttons in Xamarin.Forms. Following is my code for the Registration Page.
<StackLayout BackgroundColor="#30af91" Padding="60">
<Entry Text="{Binding FirstName}" Placeholder="First Name"/>
<Entry Text="{Binding LastName}" Placeholder="Last Name"/>
<Entry Text="{Binding UserName}" Placeholder="Last Name"/>
<Entry Text="{Binding Email}" Placeholder="Email" />
<Entry Text="{Binding Password}" Placeholder="Password" IsPassword="True"/>
<Entry Text="{Binding ConfirmPassword}" Placeholder="Confirm Password" IsPassword="True"/>
<DatePicker MinimumDate="1/1/1948" MaximumDate="12/31/2007"/>
<!--Radio buttons for Gender
1. Male 2.Female-->
<!--Radio Buttons for UserRole
1. Admin 2.Participant-->
<Button Command="{Binding RegisterCommand}" Text="Register"/>
<Label Text="{Binding Message}" />
</StackLayout>
Xamarin forms does not provide Radio Button.
You can either use
1)Switch
2)Picker
or any other component to fulfill your requirement
UPDATE
The xamarin forms update version 4.6 has introduced the Radio button control, Here is the official documentation
I think there is a simpler solution that is fairly easy and requires no libraries. Really a a radio group is just a fancy ListView. You would just need to create a viewModel for each radio button that has a IsSelected flag and switch between 2 images. I had a need to allow a user to select how long a token persisted:
XAML
<ListView
HasUnevenRows="True"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding Durations}"
ItemSelected="ListView_ItemSelected"
SelectedItem="{Binding SelectedDuration}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Orientation="Horizontal">
<Image
HeightRequest="18"
IsVisible="{Binding IsSelected}"
Source="radioButtonChecked.png"
WidthRequest="18"/>
<Image
HeightRequest="18"
IsVisible="{Binding IsUnselected}"
Source="radioButtonUnchecked.png"
WidthRequest="18"/>
<Label
Margin="8,0,0,0"
Text="{Binding Caption}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
We create a listview in our content page and listen for the ItemSelected event. Each list item is a horizontal stack panel where we flip between two images depending on the selected state
Code Behind
public partial class LoginPage : ContentPage
{
LoginPageViewModel LoginPageViewModel { get; }
public LoginTwoFactorFrequencyPage ()
{
BindingContext = LoginPageViewModel = new LoginPageViewModel();
InitializeComponent ();
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
LoginPageViewModel.UpdateSelected(e.SelectedItem as PersistenceDuration);
}
}
The page's code behind instantiates a view model and calls an UpdateSelected method with the newly selected item on the page's view model*
RadioButton ViewModel
The view model for each radio button:
public class PersistenceDuration : ViewModelBase
{
bool isSelected;
public string Caption { get; set; }
public TwoFactorTokenPersistenceDuration Duration { get; set; }
public bool IsSelected
{
get => isSelected;
set
{
isSelected = value;
OnPropertyChanged();
OnPropertyChanged("IsUnselected");
}
}
public bool IsUnselected => !IsSelected;
public PersistenceDuration(string caption, TwoFactorTokenPersistenceDuration duration)
{
Caption = caption;
Duration = duration;
IsSelected = false;
}
}
The radio button view model holds selection info and the caption. We make sure to fire OnPropertyChanged whenever the selected state changes
Page ViewModel
public class LoginPageViewModel : ViewModelBase
{
PersistenceDuration duration;
PersistenceDuration selectedDuration;
public ObservableCollection<PersistenceDuration> Durations { get; }
public PersistenceDuration SelectedDuration
{
get => selectedDuration;
set
{
if (value != null)
{
duration = value;
UpdateSelected(duration);
}
OnPropertyChanged();
}
}
public LoginTwoFactorFrequencyViewModel()
{
Durations = new ObservableCollection<PersistenceDuration>(
new List<PersistenceDuration>()
{
new PersistenceDuration(AppResources.Save_code__forever, TwoFactorTokenPersistenceDuration.Forever),
new PersistenceDuration(AppResources.ChatRequireEvery30Days, TwoFactorTokenPersistenceDuration.ThirtyDays),
new PersistenceDuration(AppResources.ChatRequireEveryLogin, TwoFactorTokenPersistenceDuration.None),
});
}
public void UpdateSelected(PersistenceDuration persistenceDuration)
{
foreach (var item in Durations)
item.IsSelected = persistenceDuration == item;
}
}
In the page view model we create a list of radio button view models that the XAML binds to. When we UpdateSelected() all the IsSelected states are updated which trigger binding updates which flip the image.
You will still need to do something about the highlight when someone selects an item, but that is easy enough to find on the internet :)
You can use XLabs plugin from manage NuGets package. After installing you can use like this:
In Xaml:
controls:BindableRadioGroup x:Name="Radiobtn"
In C#:
string[] gender = {"MAlE","FEMALE"}
Radiobtn.Add(gender)
Refer Link
https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/samples/XLabs.Samples/XLabs.Samples/Pages/Controls
You can get the radio button effect without a package. Use Labels with text unicode circle \u26AA or \u25CB. Attach a tab gesture recognizer to each label.
When tapped, change the text of the selected button to unicode circle bullet \u29BF and change the text of the other button(s) back to unicode circle \u26AA.
Test on your preferred platforms as each platform may display somewhat differently. You may need to adjust the font size as you change the text.
If you want real radiobuttons you can xlabs their package (https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Forms/XLabs.Forms/Controls/RadioButton)
Personally I'd just use a picker, Xlabs package hasn't been updated in a while so their might be some bugs in the radiobutton
You can use image as a radio button. When tou you click on it, it can change. It is not a good way to do it though.
This is xaml code:
<Image Scale="0.7" HorizontalOptions="Start" x:Name="radioButton" Source="unRadioBtn.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="radioButton_Clicked"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
And this is .cs:
private void radioButton_Clicked(object sender, EventArgs e)
{
radioButton.Source = "radioBtn.png";
}
Xamarin.Forms 4.6 introduced a new RadioButton control. You can find the documentation here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
You can use the switch component. Also you can see the implementation for a checkbox component from the XLabs project which is now discontinued, get the code and modify it as you need.
Hint: You're gonna need the custom renderers per platform for it to work .
You need to use Picker
https://developer.xamarin.com/api/type/Xamarin.Forms.Picker/
Actually it is the best alternative to RadionButton On Xamarin.forms
XLabs RadioButton and BindableRadioGroup work well: XLabs RadioButton for Xamarin Forms
Here's a simple Yes/No radio using the BindableRadioGroup:
var answers = new List<string>();
answers.Add("Yes");
answers.Add("No");
var RadioGroup = new XLabs.Forms.Controls.BindableRadioGroup()
{
ItemsSource = answers,
Orientation = StackOrientation.Horizontal
};
Xamarin Forms now provides a Radio Button control.
See docs here:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
As of XF 4.8 this is still experimental and I've not yet used this feature so can't comment on its stability.

Windows phone app, how to use narrator read page title automatically?

I'm developing windows universal app(XAML,C#) on phone, and am enabling accessibility for Narrator. Does anybody know how to get narrator automatically to read page title when a page is opened?
I tried setting automationproperties.name in page but didn't work:
<Page
x:Class="xxxxxx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AutomationProperties.Name="Page title to be read"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
The features of the Narrator for UWP are applied when you select a control in a list, or editing a textbox. If you want to read content when the app is opened you should use the SpeechSynthesizer API, which is really easy to implement:
1.- In XAML add a Media Element
<MediaElement x:Name="MediaElement"/>
2.-Then in the code behind of the page:
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
ReadTitle();
}
private async void ReadTitle()
{
var voice = SpeechSynthesizer.AllVoices.First();
SpeechSynthesizer reader = new SpeechSynthesizer() { Voice = voice };
var text= this.GetValue(AutomationProperties.NameProperty) as String;
await reader.SynthesizeTextToStreamAsync(text);
MediaElement.SetSource(stream, stream.ContentType);
MediaElement.Play();
}
You can read everything you want passing the string to the reader.
You need to make view-able by narrator. I don't believe you can declare the Name property within the Page Class. Try something like this within the content of your Page:
<HyperlinkButton
NavigateUri="www.bing.com"
AutomationProperties.AutomationID="bing url" //Not Required to work
AutomationProperties.Name="Go to the Bing Homepage"//Narrator will read this
<StackPanel>
<TextBlock Text="Bing Dot Com" />
<TextBlock Text="www.bing.com" />
<StackPanel>
</HyperlinkButton>
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.automation.peers.accessibilityview
EDIT: You may also need to programmatically set focus on the item for this to work

using TabControl in windows phone

I read the article about using a TabControl on Windows Phone application. I can avoid it to fire when it is first load. However, the selectionChanged fired twice when user click the tab. Would someone can help me how to fix it. Thanks in advance.
There is my TabControl:
<cc:TabControl Grid.Row="1" SelectionChanged="tabList_SelectionChanged" x:Name="tabList">
<cc:TabItem Height="80" Header="Events" Foreground="Black"/>
<cc:TabItem Height="80" Header="Details" Foreground="Black"/>
<cc:TabItem Height="80" Header="Notes" Foreground="Black" />
</cc:TabControl>
There is cobe behind:
public partial class Tab : PhoneApplicationPage
{
private bool blnFristLoad=true;
public Tab()
{
InitializeComponent();
tabList.SelectionChanged += new SelectionChangedEventHandler(tabList_SelectionChanged);
}
private void tabList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (blnFristLoad == false)
{
TabItem t = (sender as TabControl).SelectedItem as TabItem;
t.Content = "202020";
}
else blnFristLoad = false;
}
It's very obvious in your code. You are adding SelectionChanged event handler twice. One from your XAML code and the other from the code behind. As you are using += symbol, the eventhandler is added as a seperate instance.
Remove one of those statements.
Please use the Pivot control instead of a TabControl for the WindowsPhone. the Pivot control follows the design guidelines for the phone and looks and feels much better.

WPF4: How do you set a value in a UserControl from the Main Window?

This has to be simple, at least it was in good old .Net where it took maybe four lines of code. I'm working in VS2010, C#, WPF4.
I have a user control with a textbox. When I click a button in the main window, I want my user control textbox to reflect some text. Is this possible in WPF4 with less than 500 lines of esoteric code?
The problem is that while I know the textbox is getting the new text as evidenced from breakpoints in the user control code, that text is never being reflected to the main window. The main window still shows the original text. It has to be some kind of binding thing, and I really don't think I should have to create templates and resources and all for this simple situation. It's got to be something simple that I'm forgetting in the forest of WPF4. Below is what I have. After clicking the button, the textbox is still blank; it does not say "hello earthlings."
In the user control code:
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty TextProperty;
public UserControl1()
{
InitializeComponent();
}
static UserControl1()
{
TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UserControl1), new UIPropertyMetadata(null));
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
User control xaml:
<UserControl x:Class="WTFUserControlLibrary.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Height="164" Width="220">
<TextBox Name="txtTest" BorderBrush="red" BorderThickness="2" Height="25" Text="{Binding ElementName=UserControl1, Path=Text, Mode=TwoWay}"></TextBox>
</Grid>
(I have no idea what the text binding is supposed to be doing in this case.)
Main window code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
WTFUserControlLibrary.UserControl1 uc = new WTFUserControlLibrary.UserControl1();
uc.Text = "hello earthlings";
}
}
and the main window xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WTFUserControlLibrary;assembly=WTFUserControlLibrary"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="71,65,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<my:UserControl1 HorizontalAlignment="Left" Margin="71,94,0,0" Name="userControl11" VerticalAlignment="Top" Height="116" Width="244" />
</Grid>
Thanks Earthlings (and also those who designed this mess!)
In your method button1_Click you are creating a new user control. This is not the usercontrol in the window and is never displayed.
Instead, give your usercontrol a name in the XAML:
x:Name="uc"
Then in the button1_Click method you just remove that first line where you create a new usercontrol.
update
You want the user control XAML to look more like this:
<UserControl x:Class="WTFUserControlLibrary.UserControl1"
x:Name="thisControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Grid Height="164" Width="220">
<TextBox Name="txtTest" BorderBrush="red"
BorderThickness="2" Height="25"
Text="{Binding ElementName=thisControl, Path=Text, Mode=TwoWay}" />
</Grid>
I added x:Name="thisControl" to the root UserControl element, and then referenced this in the binding.
I'll try to explain the binding:
You have this textbox inside your user control, but you want to be able to bind the text value to something outside the user control. What you've done is set up a dependency property on the user control, and bound that textbox to it, so you are using the binding infrastructure pass values from the top level of the UserControl to constituent controls inside it.
Basically, it looks like this:
data
---> bind UserControl1.Text to data
---> bind TextBox.Text to UserControl1.Text

Resources