I am working with xamarin forms shell. I have 1 image and 1 label to assign the name and profile picture of the user.
I want every time the menu opens (press the button or drag to the right) to update that value again, but I can't find any events related to it. Someone please help me badly
Since there is no and won't be events such OnFlyoutOpened OnFlyoutClosed, you can listen to your Shell PropertyChanged event, if the property is FlyoutIsPresented then execute your code:
public AppShell()
{
InitializeComponent();
PropertyChanged += Shell_PropertyChanged;
}
private void Shell_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("FlyoutIsPresented"))
if (FlyoutIsPresented)
OnFlyoutOpened(); //you will execute your code here
else
OnFlyoutClosed();
}
Depending on your requirement you will define OnFlyoutOpened() and OnFlyoutClosed() methods.
Thanks to #PureWeen guidance in discussion.
You could use custom renderer to get the event when you press the shell hamburger icon.
[assembly: ExportRenderer(typeof(AppShell), typeof(ShellCustomRenderer))]
namespace ShellDemo.Droid
{
public class ShellCustomRenderer : ShellRenderer
{
public ShellCustomRenderer(Context context) : base(context)
{
}
protected override IShellToolbarAppearanceTracker CreateToolbarAppearanceTracker()
{
return new ToolbarAppearance();
}
}
public class ToolbarAppearance : IShellToolbarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker)
{
toolbar.NavigationClick += Toolbar_NavigationClick1;
}
private void Toolbar_NavigationClick1(object sender, Android.Support.V7.Widget.Toolbar.NavigationClickEventArgs e)
{
//this event would be fired when the hamburger icon clicked.
}
private void Toolbar_NavigationClick(object sender, Android.Support.V7.Widget.Toolbar.NavigationClickEventArgs e)
{
}
public void SetAppearance(Android.Support.V7.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
{
}
}
}
Related
I am using C# and Xamarin. I have two separate classes. One class is essentially the user interface and another class is acting as a custom built generic entry for users to input data and search for results by clicking a button.
Main UI Class:
Class MainPage
{
public MainPage
{
Content = new StackLayout
{
Children =
{
new InputClass // This is my custom built user entry class
{
}.Invoke(ic => ic.Clicked += WhenButtonPressedMethod) // The problem is here, I can't figure out how to call the button within the input class to fire a clicked event.
}
}
}
}
public async void WhenButtonPressedMethod (object sender, EventArgs e)
{
// Supposed to do stuff when the button is pressed
}
InputClass:
public class InputClass : Grid
{
public delegate void OnClickedHandler(object sender, EventArgs e);
public event OnClickHandler Clicked;
public InputClass
{
Children.Add(
new Button {}
.Invoke(button => button.Clicked += Button_Clicked)
)
}
private void Button_Clicked(object sender, EventArgs e)
{
Clicked?.Invoke(this, e);
}
}
The "InputClass" is a grid that holds a title text label, an entry and a button that a user can press to submit and search data. The button in this class is what I'm trying to actually access to invoke/cause a click event so that the method in the main UI class can be called. But, when I try to invoke a click event on the "InputClass" I can't access the button inside of it, I can only access "InputClass" itself which is just a grid with no useful event properties.
Any solutions or ideas?
If you are running into the same problem as mentioned here, follow the code on this page and read through the comments, it covers enough to be able to piece it together. My mistake was attaching Invokes to the wrong objects.
Don't know why fluent Invoke didn't work correctly.
Add the event handlers this way:
public MainPage
{
var ic = new InputClass();
ic.Clicked += WhenButtonPressedMethod;
Content = new StackLayout
{
Children = { ic }
}
}
public InputClass
{
var button = new Button;
button.Clicked += Button_Clicked;
Children.Add(button);
}
I'm fairly new to C# and I'm trying to create a Hangman game in WinForms, I've got the game functionality working, but I'm trying to create a form where the user selects a category and then the word to guess is from the category selected.
I've got a HangEventArgs like below:
public class HangEventArgs : EventArgs
{
public Category WordCategory { get; set; }
}
and a class for the data (I'm hoping to expand it to add more features in the future).
public enum Category
{
// Categories are stores here
}
public class HangData
{
public Category WordCategory { get; protected set; }
public HangData(Category askWhat)
{
WordCategory = askWhat;
}
}
And a class where the words are stored
public static class WordsToGuess
{
public static string[] Capitals =
{
"London",
"Paris" // more words here
}; // more categories here
Finally I have my button click event for all the categories, I've created my own Button as to not use the default EventArgs.
private void bCategory_Click(object sender, HangEventArgs e)
{
MainGame mg = new MainGame(new HangData(e.WordCategory));
mg.ShowDialog();
}
I've been trying to use event handlers like so
public event EventHandler<HangEventArgs>(object sender, HangEventArgs e);
But I'm not sure the proper way to implement this into my code.
If I use
bCapitals.Click += new EventHandler(bCategory_Click);
I get a no overload matches delegate error and I'm stuck on how to fix it. Thanks for the help in advance.
Create your category button like this:
public class CategoryButton : Button
{
protected override void OnClick(EventArgs e)
{
// Just discard the `e` argument and pass your own argument.
base.OnClick(new HangEventArgs { WordCategory = Category.Cities });
}
}
Subscribe the event with:
categoryButton1.Click += CategoryButton1_Click;
Use like this
private void CategoryButton1_Click(object sender, EventArgs e)
{
if (e is HangEventArgs hangEventArgs) {
MessageBox.Show(hangEventArgs.WordCategory.ToString());
}
}
Note that the click mechanism still works as expected. You don't need to fire the event yourself.
Of course you could create your own event; however, then, it must have a different name like HangClick and you must fire it yourself.
public class CategoryButton : Button
{
public event EventHandler<HangEventArgs> HangClick;
protected virtual void OnHangClick(HangEventArgs e)
{
HangClick?.Invoke(this, e);
}
protected override void OnClick(EventArgs e)
{
OnHangClick(new HangEventArgs { WordCategory = Category.Cities });
// Optionally, if you want to preserve the standard click event behaviour:
base.OnClick(e);
}
}
Subscribe with:
categoryButton1.HangClick += CategoryButton1_HangClick;
Use like this:
private void CategoryButton1_HangClick(object sender, HangEventArgs e)
{
MessageBox.Show(e.WordCategory.ToString());
}
In my application, I use an event to check network status. In the MainWindow, I instantiate some user controls (for example, I have 3 child user controls), and in one of these child controls, I need to catch the event from the App to this specific user control.
In the App I use this to start:
protected override void OnStartup(StartupEventArgs e)
{
NetworkStatus.AvailabilityChanged +=
new NetworkStatusChangedHandler(DoAvailabilityChanged);
base.OnStartup(e);
}
static void DoAvailabilityChanged(
object sender, NetworkStatusChangedArgs e)
{
//this method will send a notification
//ReportAvailability();
}
When I catch this event, I need to change the brushes in my StackPanel. After I have created the two brushes, how I can change them? I have seen some information about custom triggers. How can I use those in my StackPanel?
I used Tunneling events.
In child viewmodel:
#region Events
public readonly static RoutedEvent NetworkStatusEvent =
EventManager.RegisterRoutedEvent(
"NetworkStatusEvent",
RoutingStrategy.Tunnel,
typeof(RoutedEventHandler),
typeof(NetworkStatusViewModel));
#endregion
public void NetworkStatus_Changed(Object sender, RoutedEventArgs e)
{
Image = "home-scanner";
IsAvailable = NetworkStatus.IsAvailable ? true : false;
TextLegend = "sfsdfhf";
//RaiseEvent(new RoutedEventArgs(NetworkStatusViewModel.GreetEvent, this));
e.Handled = true;
}
In MainViewModel:
private static NetworkStatusViewModel networkStatusViewModel = new NetworkStatusViewModel();
public static NetworkStatusViewModel NetworkStatusViewModel
{
get
{
return networkStatusViewModel;
}
//set {
// networkStatusViewModel = value;
//}
}
I hope this helps.
I have a top app bar customer user control that is used to navigate in my WinRt MvvmLight application. This custom control is added to all my pages
TopAppBar User Control
<AppBarButton
x:Uid="HomeTopAppBar"
Command="{Binding HomeCommand}"
Icon="Home"/>
<AppBarButton
x:Uid="LibraryTopAppBar"
Command="{Binding LibraryCommand}"
Icon="Library"/>
These commands are added to all my ViewModels. For example,
HomeViewModel
public RelayCommand LibraryCommand {
get {
return new RelayCommand(
() => _navigationService.Navigate(typeof(LibraryPage)));
}
}
public RelayCommand HomeCommand {
get {
return new RelayCommand(
() => _navigationService.Navigate(typeof(HomePage)));
}
}
The problem I'm having is that if the user uses the top app bar, the first click works (i.e., the user is navigated to the correct page.) On the second click, the program crashes in NavigationHelper on the OnNavigatedFrom method (taken from MvvmLight). The program complains that the _pageKey is null. Is there something that I'm doing incorrectly? How exactly does a user navigate to other pages from the App Bar?
Instead of adding a command in my Appbar, i decided to use a click event. The reason why i did this is because by using the command, every viewmodel that uses my appbar needs to create that command. Here is my solution:
TopAppBar.xaml
<AppBarButton
x:Uid="HomeTopAppBar"
Click="AppBarButton_Home"
Icon="Home"/>
<AppBarButton
x:Uid="LibraryTopAppBar"
Click="AppBarButton_Library"
Icon="Library"/>
TopAppBar.xaml.cs
private void AppBarButton_Home(object sender, RoutedEventArgs e) {
SimpleIoc.Default.GetInstance<INavigationService>().Navigate(typeof(HomePage));
}
private void AppBarButton_Library(object sender, RoutedEventArgs e) {
SimpleIoc.Default.GetInstance<INavigationService>().Navigate(typeof(LibraryPage));
}
Any page navigated to from Appbar (Ex. HomePage)
public sealed partial class HomePage {
public HomePage() {
InitializeComponent();
}
public HomeViewModel ViewModel {
get {
return (HomeViewModel)DataContext;
}
}
//needed for navigation
protected override void OnNavigatedTo(NavigationEventArgs e) {
base.OnNavigatedTo(e);
}
//needed for navigation
protected override void OnNavigatedFrom(NavigationEventArgs e) {
base.OnNavigatedFrom(e);
}
}
Is there any way to hide the arrow on a ToolStripMenuItem? The arrow is enclosed in the red square.
I've found this is very helpful, you can create your own custom ToolStripRenderer inherits from ToolStripProfessionalRenderer, like this:
public class CustomToolStripRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
e.ArrowRectangle = Rectangle.Empty;//Don't draw arrow
base.OnRenderArrow(e);
}
}
//and update the Renderer property of your MenuStrip
menuStrip1.Renderer = new CustomToolStripRenderer();
UPDATE
For your requirement, there are some ways to do but I think this is a good way:
public class CustomToolStripRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
if (RenderArrow != null) RenderArrow(this, e);
base.OnRenderArrow(e);
}
public new event ToolStripArrowRenderEventHandler RenderArrow;//This will hide the default RenderArrow event which can't help you change the e argument because the default is fired after the Arrow is rendered.
}
//Now you have to create your own List<ToolStripItem> to contain all the items whose arrows should not be rendered
List<ToolStripItem> ItemsWithoutArrow = new List<ToolStripItem>();
//Add a method to add an item to that list
private void SuppressDrawArrow(ToolStripItem item)
{
if (!ItemsWithoutArrow.Contains(item)) ItemsWithoutArrow.Add(item);
}
//Assign custom ToolStripRenderer for your MenuStrip
menuStrip1.Renderer = new CustomToolStripRenderer();
//Now add a RenderArrow event handler, this RenderArrow event is the new we created in the class CustomToolStripRenderer
((CustomToolStripRenderer)menuStrip1.Renderer).RenderArrow += (s, e) =>
{
if(ItemsWithoutArrow.Contains(e.Item)) e.ArrowRectangle = Rectangle.Empty;
};
//Add some item to the ItemsWithoutArrow to test
SuppressDrawArrow(item1ToolStripMenuItem);
Another solution (I like many solutions to a problem :)
public class CustomToolStripRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
if(!itemsWithoutArrow.Contains(e.Item)) base.OnRenderArrow(e);
}
public void SuppressDrawArrow(ToolStripItem item){
if (!itemsWithoutArrow.Contains(item)) itemsWithoutArrow.Add(item);
}
public void AllowDrawArrow(ToolStripItem item){
itemsWithoutArrow.Remove(item);
}
private List<ToolStripItem> itemsWithoutArrow = new List<ToolStripItem>();
}
//Use in code
CustomToolStripRenderer renderer = new CustomToolStripRenderer();
renderer.SuppressDrawArrow(item1ToolStripMenuItem);
menuStrip1.Renderer = renderer;
//This solution fits your requirement (draw or don't draw arrow) but if you also want to change such as ArrowColor, the previous solution would be better.
I've found that we can render it freely with many options. That's great :)