Visibility (Windows Phone 7) - windows-phone-7

Sorry if I ask a basic question !
Class Customer has got string Name and int Age
In MainPage.xaml.cs I have :
ObervableCollection < Customer > Customers
In MainPage.xaml :
<Listbox x:Name = "ListCustomer"
ItemsSources = "{Binding Customers}"/>
<Button x:Name = "Button1" Visibility = "Collapsed"/>
How can i set Button1 visibility in MainPage.xaml.cs?
if(ListCustomer == null) <-- doesn't have data Button1 is collapsed, if Listbox (or Customer - I don't know)
has got data Button1 is visibled
//or if(Customers == null)
{
Button1.visibility = visibility.visibled
}
Where i can put it ?
(in Navigation To, Navigation From, or Page_Load, some where...)

Button1.Visibility = System.Windows.Visibility.Collapsed;
or
Button1.Visibility = System.Windows.Visibility.Visible;
The above code should help you make the button invisible and visible respectively.
It would be best if you could put it in the Loaded event handler. This is where you can be sure that all the UI elements are loaded.

Related

How to set AutomationId on TabbedPage bar items in Xamarin Forms app for UI test

I'm writing tests in Xamarin UI Test for a tab-based Xamarin Forms app. I'd like to set the automation Ids on each tab item so that my UI Test can click a specific tab, without referring to the tab's Text label, which is localized.
I imagine you need to use a custom renderer and set ContentDescription (Android) and AccessibilityIdentifier (iOS), and I've been trying to do that, with mixed results. What is the correct way to do this? If I'm on the right track with custom renderer, which renderer method(s) should I override in IOS/Android to achieve this?
UPDATE:
iOS:
Answer was provided by #apineda. See his solution below the question.
Android: Seems to required a custom renderer. It's a little yucky but it works. We have to recursively search the view hierarchy for the tab bar items and set "ContentDescription" for each. Since we are using a bottom-navigation bar, we search backwards for better performance. For topside navigation bar, you'll need to search for "TabLayout" instead of "BottomNavigationItemView".
[assembly: ExportRenderer(typeof(MainPage), typeof(CustomTabbedPageRenderer))]
namespace Company.Project.Droid.CustomRenderers
{
public class CustomTabbedPageRenderer : TabbedRenderer
{
private bool tabsSet = false;
public CustomTabbedPageRenderer(Context context)
: base(context)
{
}
protected override void DispatchDraw(Canvas canvas)
{
if (!tabsSet)
{
SetTabsContentDescription(this);
}
base.DispatchDraw(canvas);
}
private void SetTabsContentDescription(Android.Views.ViewGroup viewGroup)
{
if (tabsSet)
{
return;
}
// loop through the view hierarchy backwards. this will work faster since the tab bar
// is at the bottom of the page
for (int i = viewGroup.ChildCount -1; i >= 0; i--)
{
var menuItem = viewGroup.GetChildAt(i) as BottomNavigationItemView;
if (menuItem != null)
{
menuItem.ContentDescription = "TabBarItem" + i.ToString();
// mark the tabs as set, so we don't do this loop again
tabsSet = true;
}
else
{
var viewGroupChild = viewGroup.GetChildAt(i) as Android.Views.ViewGroup;
if (viewGroupChild != null && viewGroupChild.ChildCount > 0)
{
SetTabsContentDescription(viewGroupChild);
}
}
}
}
}
}
You don't need CustomRenderer for this. You just need to set the AutomationId to the children Pages of the TabPage and this is assigned to the bar Item.
Let's say you have this TabPage as below
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyGreatNamespace"
x:Class="MyGreatNamespace.MyTabPage">
<TabbedPage.Children>
<local:MainPage AutomationId="MainTab" Title="Main Page" />
<local:PageOne AutomationId="TabOne" Title="Page One" />
<local:PageTwo AutomationId="TabTwo" Title="Page Two" />
</TabbedPage.Children>
</TabbedPage>
With this configuration you will be able to do:
app.Tap("TabTwo");
And you won't need to use the Text property.
Hope this helps.-
UPDATE:
Just confirmed the above does not work with Android (noticed your original question is for Android) but only with iOS. For some reason the behavior is different.
You can still use the Localized version of the Text to "Tap it" as explained below.
A trick you can use when dealing with Localized Text is that you set the right Culture then use the same resource set in the XAML as part of the Test.
i.e
app.Tap(AppResources.MyMainTabText);

How to hide navigation Toolbar icon in xamarin?

I want to hide navigation bar button in xamarin. how can i do that using binding. Toolbar item doesn't have "IsVisible" property.
Following is my xaml code
please help me to sort out this issue.
I would suggest to build a bindable ToolBoxItem. That way you can control the visibility through a view model property.
An implementation could look like that:
public class BindableToolbarItem : ToolbarItem
{
public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BindableToolbarItem), true, BindingMode.TwoWay, propertyChanged: OnIsVisibleChanged);
public bool IsVisible
{
get => (bool)GetValue(IsVisibleProperty);
set => SetValue(IsVisibleProperty, value);
}
private static void OnIsVisibleChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var item = bindable as BindableToolbarItem;
if (item == null || item.Parent == null)
return;
var toolbarItems = ((ContentPage)item.Parent).ToolbarItems;
if ((bool)newvalue && !toolbarItems.Contains(item))
{
Device.BeginInvokeOnMainThread(() => { toolbarItems.Add(item); });
}
else if (!(bool)newvalue && toolbarItems.Contains(item))
{
Device.BeginInvokeOnMainThread(() => { toolbarItems.Remove(item); });
}
}
}
As you have discovered yourself there is not IsVisible. So you will have to implement functionality like that yourself if you still want it.
Another way would be to handle it in the pages' code-behind and remove or add the toolbar item whenever needed.
Adding and removing is simple, just add and remove items to the ToolbarItems collection: ToolbarItems.RemoveAt(0); for instance will remove the first toolbar item.
Putting #Gerald answer in action, it would be done this way:
void Done_Clicked(System.Object sender, System.EventArgs e)
{
//Do somthing and hide the done item
ShowDoneToolbarItem(false, (ToolbarItem)sender);
}
void Entry_Focused(System.Object sender, Xamarin.Forms.FocusEventArgs e)
{
//Show the done item
ShowDoneToolbarItem(true);
}
void ShowDoneToolbarItem(bool show, ToolbarItem item = null)
{
if(show)
{
ToolbarItem done = new ToolbarItem();
done.Text = "Done";
done.Clicked += Done_Clicked;
ToolbarItems.Add(done);
}
else if(item != null)
{
ToolbarItems.Remove(item);
}
}
This is cleaner and works from the code behind.
Well we need the IsVisible property for the front end, as xamarin doesn't have it, you can use Device.RuntimePlatform to check in real time which device the application is running. Since my code is in .cs of the XAML file, we can use xaml .cs to insert items into the screen.I put if () to do the logic and check if my device is on which platform, because I don't want it to display in UWP a toolbar.
The code is in .cs of the XAML file:
public kingTest()
{
InitializeComponent();
if((Device.RuntimePlatform == "Android")||(Device.RuntimePlatform == "iOS"))
{
ToolbarItem toolbar = new ToolbarItem();
toolbar.IconImageSource = "ic_ToolBar.png";
this.ToolbarItems.Add(toolbar);
}
};
I've achieved this easily using overloaded constructors. Here's an example:
View (add the name property):
<ContentPage x:Name="ContentPage"
<!-- rest of the tag -->
/>
Code-behind (add the toolbar items):
public partial class ExamplePage : ContentPage
{
public ExamplePage()
{
InitializeComponent();
BindingContext = this;
var saveToolbarItem = new ToolbarItem { Text = "Save" };
saveToolbarItem.Clicked += YourMethodToBeRan;
ContentPage.ToolbarItems.Add(saveToolbarItem);
}
public ExamplePage(Object object)
{
InitializeComponent();
BindingContext = this;
var updateToolbarItem = new ToolbarItem { Text = "Update" };
updateToolbarItem.Clicked += YourMethodToBeRan;
var deleteToolbarItem = new ToolbarItem { Text = "Delete" };
deleteToolbarItem.Clicked += YourMethodToBeRan;
ContentPage.ToolbarItems.Add(updateToolbarItem);
ContentPage.ToolbarItems.Add(deleteToolbarItem);
}
// rest of the class
}
The above pseudocode will add the "Save" toolbar item when the class is instantiated with no parameter, or the "Update" and "Delete" when a parameter is provided.
This isn't as elegant as IsEnabled / IsVisible booleans but it's a step in the right direction. Following this train of thought, you could modify the children of your toolbar during runtime to "show" and "hide" by adding and removing them as children.
Good luck!
I don't know if #tequila slammer's solution fully worked on Xamarin, but for us it only kind of works in .Net Maui (the evolution of Xamarin) and binding the IsVisible property to a variable.
Once the BindableToolbarItem is removed from the ContentPage's list of ToolbarItems, it is disconnected from the object that IsVisible is bound to forever.
For example: We want to use this control to hide or show a ToolbarItem that navigates to the admin screen, if I log in as the administrator on app launch, the item is there...great. If I then log out and log in as a non-admin, the item is not there...perfect. If I then log out and log in as an admin, the item is not there (the propertyChanged: OnIsVisibleChanged never fired)...:-(.
Not a big deal for us, if you want admin access then stopping the app and starting the app to log in as the admin is not a big ask.
In the newest release with .Net 7 the workaround works never more !
The reason is because the toolbar item which revomed will destoyed !

Change Label Value on button click in Xamarin MVVM

I'm facing an issue in Xamarin forms Mvvm. I have 2 different layouts say Layout1 and Layout2 which are bounded with a common ViewModel. Layout1 contains multiple Labels which I'm generating dynamically using for loop in xaml.cs file and bind each Label'sTextProperty using SetBinding. Layout2 contain a button.
Now I want to change Text of a particular Label when button clicked.
Layout1.xaml
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Layout1">
<StackLayout x:Name="ParentStack">
// dynamic Labels to be added here..
</StackLayout>
</StackLayout>
Layout1.xaml.cs
public partial class Layout1: StackLayout
{
public Label dummyLabel;
public Layout1()
{
InitializeComponent();
for (int i = 0; i < 3; i++)
{
dummyLabel= new Label
{
Text = " ",
};
dummyLabel.SetBinding (Label.TextProperty,"PhaseValue");
parentRowCells.Children.Add(dummyLabel);
var tapGestureRecognizer_1 = new TapGestureRecognizer();
tapGestureRecognizer_1.SetBinding(TapGestureRecognizer.CommandProperty,"LabelClicked");
tapGestureRecognizer_1.CommandParameter = dummyLabel;
dummyLabel.GestureRecognizers.Add(tapGestureRecognizer_1);
}
}
}
Layout2.Xaml
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Layout2">
<StackLayout x:Name="ParentStack">
<Button Command={Binding ButtonClickedCommand} Text="Click Me" />
</StackLayout>
</StackLayout>
ViewModel.cs
class ViewModel
{
public Label label = new Label();
public string textstring = "new text string";
ICommand _labelClicked;
public ICommand LabelClicked
{
get
{
this._labelClicked= this._labelClicked?? new Command(s =>
{
label = s as Label;
label.Text = "new text"; //this change the text of particular label when clicked but i need it from button clicked event from another layout.
// here I'm getting the instance of label which i clicked on label.
});
return this._labelClicked;
}
}
public ICommand ButtonClickedCommand{ protected set; get; }
public ViewModel()
{
this.ButtonClickCommand = new Command<Button>((key) =>
{
//here I want to change the value of label when button command is clicked.
aa.Text = "this is not changing the text";
});
}
}
Any help in this or do I need to follow some other pattern..??
My first thought would be to add each Label that you add to a List<Label> somewhere that you can access from both layouts... your View Model would seem like the logical place. Then when you click your button, you can find the particular Label whose text you want to change and change it. You will likely then have to reload your list.
However I think that a better way would be to use a ListView instead of a StackLayout. Then you can have an ItemTemplate for the ListView that includes one Label. You can then set up an ObservableCollection<T> of objects to use as the ListView.ItemsSource. You would want to make some custom object that has a Text property, or whatever you want to call the property that will hold the text for the Labels. It is better to use an object for the T in ObservableCollection<T> rather than using ObservableCollection<string> because changes to a string type will not be reflected in the ListView item, but changes to a property of an object (assuming of course that you make it a Bindable Property) will be reflected in those controls that are bound to that property. So in a nutshell, something like (in your ViewModel):
// Class level variable
ObservableCollection<CustomType> dummyLabelContents;
// then either in the ViewModel constructor or somewhere else:
dummyLabelContents = new ObservableCollection<CustomType>();
CustomType dummyText;
for (int i = 0; i < 3; i++)
{
dummyText = new CustomType
{
Text = " ",
};
}
dummyLabelContents.Add(dummyText);
And your CustomType would just be a simple class with only a BindableProperty called Text.
Set up like this, you can assign your ListView.ItemsSource to be the dummyLabelContents ObservableCollection and then whenever you add an item to the ObservableCollection, the ListView will update automatically. Also, since using a custom type with a bindable text property in the ObservableCollection, when that text property is changed the item in the ListView should also update accordingly.

How to do the navigations based on Gestures in windows phone apps?

In my app I have a Home page and 2 other pages, So I want to navigate from one page to another and viceversa, When I'm horizontally swiping from right to left and when I'm horizontally swiping from left to right it should be navigated to Home page.
Suppose, We are on Home page on swiping from right to left( Home Page ---> Page1, again swipe ---> Page2, again swipe ---> Page1 ...Like that..... ) and on all the page if I swipe from left to right it should be navigated to Home page. How to do this in windows phone 8 app ?
My Code:
if (e.HorizontalVelocity < 0) //when it is true it should navigate to next index value
{
try
{
Pivot_Main.SelectedIndex++;// here every time it's showing the same index value it is not incrementing
switch (Pivot_Main.SelectedIndex)
{
case 0:
Pivot_Main.SelectedIndex = 0;
txtBlock_Pivot_Heading.Text = "Temperature";
var brush = new SolidColorBrush(Color.FromArgb(0xFF, 0x8C, 0xC6, 0x3F));
b_celcius = true;
temperature_Page_Clear();
txtBlock_OptText.Text = "ºC";
btn_OptText.Content = "ºC";
Grid_PivotHeading.Background = brush;
Canvas_Home.Background = brush;
Canvas_DisplayName.Width = 55;
// btn_OptText.SetValue(Canvas.LeftProperty, 380.0);
break;
case 1:
Pivot_Main.SelectedIndex = 1;
txtBlock_Pivot_Heading.Text = "Length";
length_Page_Clear();
b_meter = true;
}
}
}
Please Help me, Genuine help is appreciated.
You have multiple options here.
If you can manage to do things in one page then Pivot or Panorama controls will be sufficient.
Also,if you need that every page should be different and you want to use NavigationService.Navigate() to go from one page to another then, you have event called Flick.you can manage to handle left/right swipes through this through HorizontalVelocity and VerticalVelocity of that events.
To use Flick Gesture you will need to add this code in your xaml w.r.t. to your UI element:
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Flick="OnFlick"/>
</toolkit:GestureService.GestureListener>
and in .cs its handler:
private void OnFlick(object sender, FlickGestureEventArgs e)
{
// User flicked towards left
if (e.HorizontalVelocity < 0)
{
//your respective navigation to other page
}
// User flicked towards right
if (e.HorizontalVelocity > 0)
{
//your respective navigation to other page
}
Details of Gesture support you can get here

how to add/show a UserControl (e.g. popup) in a WP7 app page?

hi i have created a user control.
now i want to add this control to a page e.g. when the user clicks a button (important is, that i dont want to add it direcly in xaml, i want to add id in the c# code section)
how to so this?
In your button's Click event, you could do something like:
MyControl control = new MyControl();
// Set whatever properties you need in your control here
LayoutRoot.Children.Add(control);
if (listBox1.Items.Count == 0)
{
Popup popup = new Popup();
WPCpopup po = new WPCpopup(popup);
popup.Width = System.Windows.Application.Current.Host.Content.ActualWidth;
popup.Child = po;
popup.VerticalOffset = 300;
popup.IsOpen = true;
}
WPCpopup is usercontrol

Resources