I'm creating a Xamarin.Forms app using c#.
There is a Button in a Page and i want to add a new Label in StackLayout that is in the Main Page when the Button is clicked.
I tried to set the FieldModifier property of the StackLayout public in the XAML file, but it didn't work...
This is the layout code (i want to add the label into MainStackLayout) and the cs method of the Button click:
<ContentPage.Content>
<ScrollView>
<StackLayout BackgroundColor="white">
<StackLayout Orientation="Horizontal" x:Name="MainStackLayout" x:FieldModifier="public" >
</StackLayout>
<Button
Text="Add Counter"
BackgroundColor="darkgreen"
HorizontalOptions="FillAndExpand"
CornerRadius="0"
HeightRequest="80"
TextColor="white"
FontAttributes="Bold"
x:Name="AddCounter_btn"
Clicked="AddCounter_btn_Clicked"
>
</Button>
</StackLayout>
</ScrollView>
</ContentPage.Content>
private void StartCount_btn_Clicked(object sender,EventArgs e)
{
Label NCounterName =new Label();
NCounterName.Text = counter_txt.Text.ToString();
Label NCounterNumber = new Label();
NCounterNumber.Text = "0000";`enter code here`
}
Let's say you have a button in Page1 which is StartCount_btn, and when you click this button, you want to add some labels to MainStackLayout in Page2.
In Page1, send a addLabelNotification when you click the StartCount_btn button:
private void StartCount_btn_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send<Object>(this, "addLabelNotification");
}
In Page2, Subscribe to the message and add labels when receive the message:
public partial class Page2 : ContentPage
{
public Page2()
{
InitializeComponent();
MessagingCenter.Subscribe<Object>(this, "addLabelNotification", (sender) =>
{
// Do something whenever the "addLabelNotification" message is received
Label NCounterName = new Label();
NCounterName.Text = "counter_txt";
Label NCounterNumber = new Label();
NCounterNumber.Text = "0000";
MainStackLayout.Children.Add(NCounterName);
MainStackLayout.Children.Add(NCounterNumber);
});
}
}
Refer: messaging-center
I wrote this code here, could not check it but it will work. Your button gives you enough information to reach any View. You just use parent-child controls.
private void StartCount_btn_Clicked(object sender,EventArgs e)
{
if(sender is Button myButton)
{
if(myButton.Parent is StackLayout myStackLayout)
{
Label NCounterName =new Label();
//set your label's text
myStackLayout.Add.Children(NCounterName);
}
}
}
Related
My problem would be, I want to make a menu with MaterialDesign and I want the button style to change when I go to one of the menu items in the menu. However, when I overwrite the MaterialDesign style, I cannot reset it. I wanna make somethin like like this:enter image description here
Thats my menu code:
<Grid>
<StackPanel Orientation="Horizontal" Height="35" VerticalAlignment="Top" >
<Button x:Name="User_B" Content="Users" MinWidth="100" Click="User_B_Click"/>
<Button x:Name="Auto_B" Content="Auto" MinWidth="100" Click="Auto_B_Click"/>
<Button x:Name="Clien_B" Content="Client" MinWidth="100" Click="Clien_B_Click" />
<Button x:Name="Failure_B" Content="Failure" MinWidth="100" Click="Failure_B_Click"/>
<Button x:Name="Settings_B" Content="Settings" MinWidth="100" Click="Settings_B_Click"/>
</StackPanel>
<Frame x:Name="Main" Margin="0,35,0,0" NavigationUIVisibility="Hidden"/>
</Grid>
My c# code:
private void User_B_Click(object sender, RoutedEventArgs e)
{
Style selectstyle = new Style();
selectstyle.TargetType = typeof(Button);
selectstyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030"))));
selectstyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000"))));
User_B.Style = selectstyle;
Auto_B.Style = null;
}
private void Auto_B_Click(object sender, RoutedEventArgs e)
{
Style selectstyle = new Style();
selectstyle.TargetType = typeof(Button);
selectstyle.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#303030"))));
selectstyle.Setters.Add(new Setter(Button.ForegroundProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#d50000"))));
Auto_B.Style = selectstyle;
User_B.Style = null;
}
and this is how it looks now:enter image description here
First you need to do this in all of your pages :
MainWindow mw = null;
public Employees(MainWindow mw)
{
InitializeComponent();
this.mw = mw;
}
Create a null object for your MainWindow , than give a parameter to your Page method , then in the method , you declare the MainWindow like I show you in the code.
After you done with this , then you need to go to the MainWindow.xaml.cs and you have to do this:
public MainWindow()
{
InitializeComponent();
employees = new Employees(this);
Presenter.Content = employees;
}
Employees employees = null;
Create a null object for your Page , and in the MainWindow method you have to declare the Page like this.
After that , you just need a Loaded and an Unloaded event to your page :
private void Page_Loaded(object sender, RoutedEventArgs e)
{
mw.EmployeesButton.Background = (Brush)new BrushConverter().ConvertFrom("#006B60");
}
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
mw.EmployeesButton.Background = (Brush)new BrushConverter().ConvertFrom("#009688");
}
You can use any color you want , I hope its helps :D
I created control in WPF from C# and find that control on button click but not found
public MainWindow()
{
InitializeComponent();
TextBox textBox = new TextBox();
textBox.Name = "childTextBox";
TextBoxes.Add(textBox);
StackPanelParent.Children.Add(textBox);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var findTextBox = (TextBox)this.FindName("childTextBox");
//it's give null
}
XAML Code
<StackPanel Margin="152,103,191,56">
<Label Name="Loader" Visibility="Collapsed">Loader</Label>
<Button Content="Click Me" HorizontalAlignment="Left" Margin="342,199,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>-->
<StackPanel Name="StackPanelParent">
</StackPanel>
<Button Click="Button_Click">Check</Button>
</StackPanel>
When you dynamically create a component they cannot be found by FindName unless you register them first like this:
public MainWindow()
{
InitializeComponent();
TextBox textBox = new TextBox();
textBox.Name = "childTextBox";
TextBoxes.Add(textBox);
StackPanelParent.Children.Add(textBox);
// register name
RegisterName(textBox.Name, textBox);
}
Im using a stacklayout that contains some other elements and a button.
<StackLayout x:Name="layout">
<Button Text="Button" Clicked="Action"/>
<StackLayout/>
Is there a way to get the StackLayout that contains the button when it is clicked?
Use Parent property
void Action(object sender, EventArgs args)
{
var button = sender as Button;
var stackLayout = button.Parent as StackLayout;
stackLayout.Children.Remove(button);
}
I have a Button with a TextBlock embedded inside. When the Button is clicked, I want to be able to fetch the TextBlock inside it and modify it's members.
Here is how my button is setup:
<Button Click="Select_Click" Style="{StaticResource ButtonStyle}" HorizontalAlignment="Left" Padding="0,20,20,20">
<TextBlock Text="My text" FontSize="20" Style="{StaticResource TextBlockStyle}"/>
</Button>
In my code behind I want to be able to access the embedded TextBlock:
public void Select_Click(object sender, RoutedEventArgs e)
{
// Get the `TextBlock` from `sender` here
}
I've taken a look at the visual tree of the Button but I'm not seeing the TextBlock. I called GetVisualChildren() on the Button but I only see a Grid and no way to get to the Textblock.
The content of the Button is stored in its Content property and in your case, the TextBlock is the content of the Button.
public void Select_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
TextBlock textBlock = (TextBlock)button.Content;
}
Just do some casting and it's pretty simple
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Establish_handlers();
}
void Establish_handlers()
{
Mybutton.Click += Mybutton_Click;
}
private void Mybutton_Click(object sender, RoutedEventArgs e)
{
Button clicked_button = (Button)sender;
TextBlock desired_text = (TextBlock)clicked_button.Content;
Textbox_Show_Button_Content.Text = desired_text.Text;
}
}
<StackPanel>
<Button x:Name="Mybutton">
<TextBlock>Hello</TextBlock>
</Button>
<TextBox x:Name="Textbox_Show_Button_Content"></TextBox>
</StackPanel>
I have a second .xaml page set up under the name Page2.xaml and I want to make it so that when my button is clicked, the user is taken to Page2.xaml
I have this for my button inside of my Page1.xaml:
<Grid>
<Button x:Name="localModeBtn"
Style="{StaticResource MainButtonStyle}"
Content="local mode"
Click="localModeBtn_Click" />
</Grid>
And for the button event handler:
private void localModeBtn_Click(object sender, RoutedEventArgs e)
{
Uri uri = new Uri("Page2.xaml", UriKind.Relative);
this.NavigationService.Navigate(uri);
}
Upon clicking the button I receive an error that says "Cannot locate resource page2.xaml"
The thing is that Page2.xaml is in the same folder as Pag1.xaml so I can't see where I've gone wrong?
Solution to my own question:
I feel a bit silly providing a solution to my own question but thanks to Jasti's link I was able to sort my code out. As he had only posted a comment, I can't mark it as an answer, so here is the solution.
I changed the NavigationWindow to a Window and inserted:
<DockPanel>
<Frame x:Name="_NavigationFrame" NavigationUIVisibility="Hidden" />
</DockPanel>
And within the constructor of the MainWindow.xaml.cs I added:
_NavigationFrame.Navigate(new Page1());
Then the last step was to adjust the button event handler to:
this.NavigationService.Navigate(new Uri("Pages/Page2.xaml", UriKind.Relative));
You should use this, this worked for me:
var Page2= new Page2(); //create your new form.
Page2.Show(); //show the new form.
this.Close(); //only if you want to close the current form.
There is a variable type of a page with the page.xaml right name in your solution.
after that, you should use its methods to do it functionally.
Use any container and bind the content to any property in your viewmodel or codebehind.
After that you just have to update the property by setting a new page and call the PropertyChanged-event (see INotifyPropertyChanged interface). This will update the content of your container and you can display anything you want.
In case you want a separate window
NavigationWindow navWIN = new NavigationWindow();
navWIN.Content = new pageWFbchAdmin();
navWIN.Show();
//winBchAdmin.ShowDialog();
You don't need any C# code for this, just do it in XML:
<Button Content="local mode"
Command="NavigationCommands.GoToPage"
CommandParameter="/Page2.xaml"/>
(Reformatted code not tested)
private void Navigate_Click(object sender, RoutedEventArgs e)//By Prince Jain
{
this.NavigationService.Navigate(new Uri("Page3.xaml", UriKind.Relative));
}
My solution was adding a frame in the main window MainWindow.xaml
<Frame Name="Main" Content="" Margin="127,0,0,0" Background="#FFFFEDED" />
For navigation:
1- Navigating from the main windows on button click:
private void Button_Click(object sender, RoutedEventArgs e)
{
// navigate to pages/projects.xaml inside the main frame
Main.Content = new MyProject.Pages.Projects();
}
2- In case of navigation from the page inside a frame ex Projects.xaml
// declare a extension method in a static class (its your choice if you want to reuse)
// name the class PageExtensions (you can choose any name)
namespace MyProject
{
public static class PageExtensions
{
public static void NavigateTo(this Page page, string path)
{
Frame pageFrame = null;
DependencyObject currParent = VisualTreeHelper.GetParent(page);
while (currParent != null && pageFrame == null)
{
pageFrame = currParent as Frame;
currParent = VisualTreeHelper.GetParent(currParent);
}
if (pageFrame != null)
{
pageFrame.Source = new Uri(path, UriKind.Relative);
}
}
}
}
// to navigate from 'pages/projects.xaml' to another page
// heres how to call the extension on button click
this.NavigateTo("NewProject.xaml");
In addition, you can add another extension method that expects another Page object, in case you want to pass parameters to the constructor
// overloading NavigateTo
public static void NavigateTo(this Page page, Page anotherPage)
{
Frame pageFrame = null;
DependencyObject currParent = VisualTreeHelper.GetParent(page);
while (currParent != null && pageFrame == null)
{
pageFrame = currParent as Frame;
currParent = VisualTreeHelper.GetParent(currParent);
}
// Change the page of the frame.
if (pageFrame != null)
{
pageFrame.Navigate(anotherPage);
}
}
// usage
this.NavigateTo(new Pages.EditProject(id));
First of all, you'll need a frame in your window to hold the pages, so in my MainWindow.xaml I'll add a frame like this:
<Frame x:name="mainFrame"/>
Then We'll add an event listener to our navigation button in our MainWindow.xaml like this:
<Button
x:Name="navBtn"
Content="LIVE VIEW"
Click="NavBtn_Click">
</Button>
Now after we've set our window xaml up, we'll go to MainWindow.xaml.cs and write our code:
//this function should be automatically generated
private void NavBtn_Click(object sender, RoutedEventArgs e)
{
//we'll write this line, which opens our page
mainFrame.Content = new YourPage();
}
and that's it your navigation is ready!
In View (.xaml file):
<StackPanel>
<TextBlock>Outside area of frame</TextBlock>
<StackPanel Height="20" Width="400" VerticalAlignment="Top" Orientation="Horizontal">
<Button Content="Page 1" Width="200" Click="Button_Click"/>
<Button Content="Page 2" Width="200" Click="Button_Click_1"/>
</StackPanel>
<Frame Name="Main" Height="300" Width="700" Background="LightGray">
</Frame>
</StackPanel>
In code behind (.xaml.cs file):
private void Button_Click(object sender, RoutedEventArgs e)
{
Main.Content = new Page1();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Main.Content = new Page2();
}
Thesse two buttons will now help you to navigate between pages named Page1 and Page2. (Please take care of namespaces if the pages are present in folders or so).