in my project i have a login page named login.xaml and i had loginViewModel.cs for using MVVM Approach.. At beginning i wrote this.dialogResult=true in my code-behind page(login.xaml.cs) and use the code means it closes the childwindow.. here i need to close the childwindow(login.xaml) from viewmodel(loginviewmodel).
login.xaml:
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
if (txtuser.Text.Trim() != "" && txtpass.Password != "")
{
(DataContext as LoginViewModel).UserValidation(txtuser.Text.Trim(),txtpass.Password.Trim());
}
}
loginviewmodel.cs:
public void UserValidation(string name, string pass)
{
IsBusy =true;
uname=name;
pword=pass;
// ----* (Follow * for the continuation )
}
*--> here i need to close the childwindow.. how to close it..
I got the same problem and solved it... So I have my Child Window and the button Cancel:
<Button x:Name="CancelButton" Content="Cancel" Command="{Binding CancelCommand}" CommandParameter="{Binding ElementName=SignUpPopup}" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1"/>
and what I do is I pass the object Child Window - that has Name="SignUpPopup" trough the ExecuteCancelCommand parameter, param. and in the view model you have:
public void ExecuteCancelCommand(object param)
{
(param as Signup).Close();
// MessageBox.Show("Window should close now");
}
Signup is the child window type.
Hope this helps,
Vlad
Related
I want to be able to add an event from my custom control to the outside world
as I change a value in my custom control, I use TwoWay, but I also want an event to be generated in my main app
I just cannot find anything relevant to this
the main app xaml contains this line :
<custom:MyComp x:Name="myComp" ValueChanged="SomeFunction" Value="{ Binding Path=someIntVariable, Mode=TwoWay}"></custom:MyComp>
how do I implement a ValueChanged event in the custom control ?
my control xaml:
<UserControl ...>
<StackPanel Orientation="Horizontal" >
...
<TextBox x:Name="MyCompTextBox" Width="50" Height="20" TextChanged="MyCompTextBox_TextChanged"/>
...
</StackPanel>
</UserControl>
the code
public partial class MyComp: UserControl
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(MyComp), new FrameworkPropertyMetadata(0, OnValuePropertyChangedCallback));
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void OnValuePropertyChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
MyComp mMyComp= source as MyComp;
int newValue=(int)e.NewValue;
myComp.MyCompTextBox.Text = newValue.ToString();
}
public MyComp()
{
InitializeComponent();
}
private void MyCompTextBox_TextChanged(object sender, EventArgs e)
{
int _bpm = int.ParseMyCompTextBox.Text);
Value = _bpm;
MyCompTextBox.Text = Value.ToString();
// here I want to trigger an even to the main app !!!
}
}
thanks for your help
Before starting, as is stated in the title, I'm learning .NET MAUI and I'm very new in this.
My problem is that I can't find a way to share information from a page to a previous page.
What I'm trying to do is the following:
In the MainPage, have a button that once pressed, sends the user to another page, let's call it LoginPage, there, ask the user for his name, and after the input, redirect him to the previous page showing an "Hello {Name}, and welcome!"
MainPage code:
string Name = "";
string greetings = "";
async private void LogintBtn_Clicked(object sender, EventArgs e)
{
{
await Navigation.PushAsync(new LoginPage());
}
greetings = $"Welcome {Name}!";
Greetinglbl.Text = greetings;
}
Log in code:
public string name { get; set; }
private void btnRegister_Clicked(object sender, EventArgs e)
{
if (ValidateName()==false) { return; };
Navigation.PopAsync();
}
private bool ValidateName()
{
if (string.IsNullOrWhiteSpace(txtRegistro.Text))
{
return false;
}
else
return true;
}
Beside this, I don't know how to share information between these pages.
I have seen that a lot of devs use MVVM but I can't get a Beginners guide propperly, even watching the .NET MAUI Beginners Guides from James Montemagno doesn't help me.
I've also tried using something like
await Shell.Current.GoToAsync($"LoginPage?Name={Name}");
that, for what I read is used to send data but don't know where to put it, plus triying to navigate with the same line throws an error (null).
Plus, most of the videos only shows how to send Data to the next Page, not the previous, and usually to a collection, and some of them import NuGet Packages that I don't see to be necessary in this project.
In your scenario, you could share the data through Constructor, here's the code snippet below for your reference.
MainPage:
Xaml:
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Label Text="MainPage"></Label>
<Button
Text="To Login Page"
Clicked="OnClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ScrollView>
Code-behind:
public MainPage()
{
InitializeComponent();
}
public MainPage(string a)
{
InitializeComponent();
App.Current.MainPage.DisplayAlert("Welcome Back",a,"OK");
}
private async void OnClicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new LoginPage());
}
LoginPage:
Xaml:
<VerticalStackLayout>
<Label Text="LoginPage"></Label>
<Entry x:Name="myentry"/>
<Button
Text="ToMain"
Clicked="BackTo"
HorizontalOptions="Center" />
</VerticalStackLayout>
Code-behind:
public LoginPage()
{
InitializeComponent();
}
private async void BackTo(object sender, EventArgs e)
{
await Navigation.PushModalAsync(new MainPage(myentry.Text));
}
Last but not least, in your App.xaml.cs, use it like below:
MainPage = new NaviagtionPage(new MainPage())
I'm trying to implement TapGestureRecognizer which will be called in ViewModel (xaml.cs) not in View class...
Here is sample code in xaml file: (IrrigNetPage.xaml)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:i18n="clr-namespace:agroNet.AppResource;assembly=agroNet"
xmlns:viewModels="clr-namespace:agroNet.ViewModel"
x:Class="agroNet.View.IrrigNetPage"
BackgroundColor="#EBEBEB">
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="HideListOnTap"/>
</Grid.GestureRecognizers>
</Grid>
I implemented HideListOnTap in xaml.cs page (view) like this: (IrrigNetPage.xaml.cs)
int visibility = 1;
private void HideListOnTap(object sender, EventArgs e)
{
visibility++;
if ((visibility % 2) == 0)
{
IrrigList.IsVisible = false;
}
else
{
IrrigList.IsVisible = true;
}
}
It's working fine, but how to do the same thing usin ViewModel?
(How to bind Gesture recognizer from (IrrigNetPage.xaml) with HideListOnTap in IrrigNetViewModel )
Use a Command whenever you want to handle some event in the ViewModel. Without passing any arguments the code would look like as follows
<!-- in IrrigNetPage.xaml -->
<TapGestureRecognizer Command="{Binding HideListOnTapCommand}"/>
And in the ViewModel IrrigNetPageViewModel.cs
public ICommand HideListOnTapCommand { get; }
public IrrigNetPageViewModel()
{
HideListOnTapCommand = new Command(HideListOnTap);
// if HideListOnTap is async create your command like this
// HideListOnTapCommand = new Command(async() => await HideListOnTap());
}
private void HideListOnTap()
{
// do something
}
i got some troubles with using the PageRenderer.
MainPage.xml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="abc.CustomView">
<ContentPage.Content>
<StackLayout>
<Button Text="scann" Clicked="BtnScannClicked"></Button>
</StackLayout>
</ContentPage.Content>
MainPage.cs
async void BtnScannClicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new CustomView());
}
CustomView.Xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="abc.CustomView">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
CustomView.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomView : ContentPage
{
public CustomView ()
{
InitializeComponent ();
}
}
DemoPage.cs (which is my CustomRenderer)
[assembly: ExportRenderer(typeof(CustomView), typeof(DemoPage))]
namespace abc.UWP
{
class DemoPage: PageRenderer
{
Page page;
Application app;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
app = Application.Current;
SetupUserInterface();
this.Children.Add(page);
}
catch (Exception ex)
{
Debug.WriteLine(#" ERROR: ", ex.Message);
}
}
void SetupUserInterface()
{
var stackPanel = new StackPanel();
page = new Page();
page.Content = stackPanel;
}
}
}
There is always a
Exception thrown: 'System.InvalidOperationException' in Xamarin.Forms.Platform.UAP.dll
error during the build.
But I guess this is not really a problem with the PageRenderer. Seems that this appears during the ClickEvent.
There is always a Exception thrown: 'System.InvalidOperationException' in Xamarin.Forms.Platform.UAP.dll error during the build.
The problem is that you have not add the MainPage to NavigationPage.
The PushAsync method is not supported globally on Windows. You could add the the following code to the app.xaml.cs file to solve the issue.
public App()
{
InitializeComponent();
var RootNav = new NavigationPage(new MainPage());
MainPage = RootNav;
}
PushModalAsync - Push a page into a modal context. This will create a new, independent, Navigation context within the application. The modal that is created can be dismissed with a hardware back button; there appears to no way to stop this functionality.
So the PushModalAsync method does not depend on NavigationPage, it will work in your current scenario.
Put my application is always crashing (has exit code -1) after the navigation to DemoPage.cs. The Implementation should be ok, or not?
I have found that you have not implemented ArrangeOverride method in your PageRenderer. And you will not see the content of page.
protected override Size ArrangeOverride(Size finalSize)
{
page.Arrange(new Windows.Foundation.Rect(0, 0, finalSize.Width, finalSize.Height));
return finalSize;
}
I have a requirement as follows, I want to print the screen elements present on the screen to printer. Implementation is done through MVVM. so If I click on print button on the screen it should display a print dialogue and selecting the printer should proceed with printing all the UI elemnts with their data . I have tried with solution present at print WPF visual from viewmodel but its missing the margings and not displaying properly
Also I have another button Print Preview which should display print preview dialogue to see the preiview.
Thanks in advance.
Regards,
Krishna.
In my opinion the printing of the View in an MVVM application is not the responsiblity or concern of the ViewModel. I believe you are better of doing this from the View.
How I've achieved this before is to use a WPF Behavior on a button - I use a Behavior because I'm using DataTemplates for the View and there isn't a 'code behind' file.
The Behavior exposes a DependencyProperty, this is a binding to what is to be printed or contains what is going to be printed.
XAML:
<Button Margin="0,2,5,2"
HorizontalAlignment="Right"
Content="PRINT"
ToolTip="Prints the current report">
<i:Interaction.Behaviors>
<b:ReportPrintClickBehavior Content="{Binding ElementName=SelectedReportContent, Mode=OneWay}" />
</i:Interaction.Behaviors>
</Button>
To reference the Behavior in the XAML you'll need to reference System.Windows.Interactivity, this can be found on NuGet here.
Code-Behind (Behavior):
In this case I'm printing a FlowDocument hosted inside a FlowDocumentReader.
public sealed class ReportPrintClickBehavior : Behavior<Button>
{
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content",
typeof(DependencyObject),
typeof(ReportPrintClickBehavior),
new PropertyMetadata(null));
public DependencyObject Content
{
get { return (DependencyObject)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
AssociatedObject.Unloaded += OnUnloaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnLoaded;
AssociatedObject.Unloaded -= OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs args)
{
AssociatedObject.Click += OnClick;
}
private void OnUnloaded(object sender, RoutedEventArgs args)
{
AssociatedObject.Click -= OnClick;
}
private void OnClick(object sender, RoutedEventArgs args)
{
var flowDocumentReader = Content.GetVisualDescendent<FlowDocumentReader>();
if (flowDocumentReader != null)
{
flowDocumentReader.Print();
}
}
}