I am trying to make when clicking on a Label enter text in an Entry. I am doing it with TapGestureRecognizer and command but it does nothing, I don't know where the problem can be. The x:Name of the Entry is EntryControl.
My Label:
<Label Margin="10"
FontSize="30"
Text="{Binding EmojiSource}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EmojiTappedCommand}" />
</Label.GestureRecognizers>
</Label>
Behind Code:
public ICommand EmojiTappedCommand { get; private set; }
public Editor(){
EmojiTappedCommand = new Command(EmojiButtonCommand);
}
private void EmojiButtonCommand()
{
EntryControl.Text ="Tapped";
}
Please add BindingContext = this; in the background code.
public partial class MainPage : ContentPage
{
public ICommand EmojiTappedCommand { get; private set; }
public string EmojiSource { get; set; }
public MainPage()
{
InitializeComponent();
EmojiSource = "test";
EmojiTappedCommand = new Command(EmojiButtonCommand);
BindingContext = this;
}
private void EmojiButtonCommand()
{
EntryControl.Text = "Tapped";
}
Here is running GIF.
Related
All the examples for RadioButtons I've found so far have the values hard-coded in the xaml for the page. I'm looking to feed a list of strings (for now) from a database and running into an issue with the GroupName.
My data template for a radio display type:
<DataTemplate x:Key="RadioTemplate">
<StackLayout>
<Label
Text="{Binding Name}"
Style="{StaticResource LabelStyle}">
</Label>
<ListView ItemsSource="{Binding Choices.Choices}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<RadioButton Value="{Binding}"
Content="{Binding}"
GroupName="someGroupName"
CheckedChanged="OnRadioChanged">
</RadioButton>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</DataTemplate>
MainPageViewModel.cs
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Xamarin.Forms;
using FieldDataTemplateSelectorSample.Validations;
namespace FieldDataTemplateSelectorSample
{
public class MainPageViewModel : ValidationViewModelBase
{
public MainPageViewModel()
{
_fields = new ObservableCollection<FieldViewModel>();
}
private ObservableCollection<FieldViewModel> _fields;
public ObservableCollection<FieldViewModel> Fields
{
get { return _fields; }
set
{
_fields = value;
RaisePropertyChanged();
}
}
private bool _showValidationSummary;
public bool ShowValidationSummary
{
get { return _showValidationSummary; }
set
{
_showValidationSummary = value;
RaisePropertyChanged();
}
}
ICommand _submitCommand;
public ICommand SubmitCommand
{
get => _submitCommand ?? (_submitCommand = new Command(ValidateAndSave));
}
private void ValidateAndSave(object obj)
{
ValidateAll();
if (ErrorStateManager.HasError)
{
ShowValidationSummary = true;
}
else
{
ShowValidationSummary = false;
}
}
}
}
using System.Collections.Generic;
using Xamarin.Forms;
using FieldDataTemplateSelectorSample.Validations;
namespace FieldDataTemplateSelectorSample
{
public class FieldViewModel : ValidationViewModelBase
{
public FieldViewModel()
{
_choices = new ChoiceViewModel();
}
private string _value;
public long Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Code { get; set; }
public string Value
{
get
{
return _value;
}
set
{
_value = value;
RaisePropertyChanged();
Validate();
}
}
public string PlaceholderText { get; set; }
public int SortOrder { get; set; }
public string DisplayType { get; set; }
public bool IsReadOnly { get; set; }
public bool IsEnabled { get; set; }
private ChoiceViewModel _choices;
public ChoiceViewModel Choices
{
get
{
return _choices;
}
set
{
_choices = value;
RaisePropertyChanged();
}
}
void OnChoicesRadioButtonCheckedChanged(object sender, CheckedChangedEventArgs e)
{
// what else do we need to do? Update value?
RaisePropertyChanged();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace FieldDataTemplateSelectorSample
{
public class ChoiceViewModel
{
public ChoiceViewModel()
{
Choices = new List<string>();
}
public string Code { get; set; }
public List<string> Choices { get; set; }
}
}
As long as I hard-code the GroupName for the RadioButton in the ViewCell, everything works but that I'll end up with one group name for every single radio button on the page. I've tried adding the property to the StackLayout in the template:
<StackLayout RadioButtonGroup.GroupName="someGroup">
and taking it out out of the RadioButton but when I put a breakpoint in OnRadioChanged, the GroupName comes in as null.
I'd like to use the Code property in the ChoiceViewModel as the group name but haven't gotten the relative binding correct yet. Any help with the binding or different way to do the DataTemplate is appreciated.
you could use a bindable StackLayout which will give you more control over the containter
<StackLayout>
<Label Text="{Binding Name}" Style="{StaticResource LabelStyle}" />
<StackLayout RadioButtonGroup.GroupName="{Binding Name}"
BindableLayout.ItemsSource="{Binding Choices.Choices}" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<ViewCell>
<RadioButton Value="{Binding}" Content="{Binding}"
CheckedChanged="OnRadioChanged" />
</ViewCell>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
This question already has answers here:
using of INotifyPropertyChanged
(3 answers)
Closed 1 year ago.
I have text block that i want to chance from false to true by his binding property.
The property has change to true but the text of text box stay false.
How can I do this right.
Thank for the help.
<TextBlock x:Name="resBlock" Grid.Row="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="250" Height="50" Text="{Binding Source={StaticResource Locator}, Path=Main.Result}" TextAlignment="Center" FontSize="30" />
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
LoginCommand = new RelayCommand(Login);
user = new User();
}
DataService service = new DataService();
public User user { get; set; }
public bool Result { get; set; }
public ICommand LoginCommand { get; }
public async void Login()
{
Result = await service.LoginAsync(user); // get True
}
}
To change the amount of control with the viewmodel, you must implement the INotifyPropertyChanged interface.
change MainViewModel to:
public class MainViewModel : ViewModelBase, INotifyPropertyChanged
{
public MainViewModel()
{
LoginCommand = new RelayCommand(Login);
user = new User();
}
DataService service = new DataService();
public User user { get; set; }
public ICommand LoginCommand { get; }
public async void Login()
{
Result = await service.LoginAsync(user); // get True
}
private bool result;
public bool Result
{
get { return result; }
set
{
result = value;
OnPropertyChange(nameof(Result));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Im learning MVVM at the moment and made a Login Window which opens first.
After Logging in, my MainWindow opens. The MainWindows Title is set via Property in MainWindowViewModel but doesn't shown (its empty) now when I open this window via LoginWindow instead of making it the StartUp Window.
This is the Code how I open MainWindow from Login.
LoginViewModel.cs
if (r)
{
CurrentUser.Username = Username;
Messenger.Default.Send(new NotificationMessage("CloseWindow"));
}
LoginView.xaml.cs
public Login()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this, (message) =>
{
switch (message.Notification)
{
case "CloseWindow":
Messenger.Default.Send(new NotificationMessage("NewCourse"));
var MainWindow = new MainWindow();
MainWindow.Show();
this.Close();
break;
}
});
}
MainViewModel.cs
public MainViewModel()
{
if (IsInDesignMode)
{
WindowTitle = "Controlcenter (Designmode)";
CurrentUserLoggedIn = "Logged in as: " + CurrentUser.Username;
CurrentVersion = "Version: " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
else
{
WindowTitle = "Controlcenter";
CurrentUserLoggedIn = "Logged in as: " + CurrentUser.Username;
CurrentVersion = "Version: " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
}
public string WindowTitle { get; private set; }
public string CurrentUserLoggedIn { get; private set; }
public string CurrentVersion { get; private set; }
I dont know why but I think MainViewModel() isn't called.
Im using MVVMLight and PropertyChanged.Fody.
So my ViewModelLocator looks like this
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<DataErrorInfoViewModel>();
SimpleIoc.Default.Register<LoginViewModel>();
}
public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
public LoginViewModel Login => ServiceLocator.Current.GetInstance<LoginViewModel>();
public DataErrorInfoViewModel DataErrorInfo => ServiceLocator.Current.GetInstance<DataErrorInfoViewModel>();
Is there something wrong in ViewModelLocator?
Edit:
MainWindow.xaml
<Window x:Class="Ui.Desktop.MainWindow"
[...]
xmlns:logic="clr-namespace:Logic.Ui;assembly=ControlcenterMVVM.Logic.Ui"
Title="{Binding WindowTitle, Mode=OneWay}"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<DataTemplate x:Name="firmcustomerViewTemplate" DataType="{x:Type logic:FirmcustomerViewModel}">
<local:Firmcustomer DataContext="{Binding}" />
</DataTemplate>
<DataTemplate x:Name="privatecustomerViewTemplate" DataType="{x:Type logic:PrivatecustomerViewModel}">
<local:Privatecustomer DataContext="{Binding}" />
</DataTemplate>
</Window.Resources>
<Grid>
[...]
<Label Content="{Binding CurrentUser}" FontWeight="Normal" FontSize="13" />
<Label Content="{Binding CurrentVersion}" />
</StackPanel>
<ContentControl Grid.Row="0" Grid.Column="1" Grid.RowSpan="3" Content="{Binding}" />
</Grid>
And MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new FirmcustomerViewModel();
}
private void firmcustomer_Click(object sender, RoutedEventArgs e)
{
DataContext = new FirmcustomerViewModel();
}
private void privatecustomer_Click(object sender, RoutedEventArgs e)
{
DataContext = new PrivatecustomerViewModel();
}
}
So what does PropertyChanged.Fody for me now?
In MainWindowViewModel i just add the Properties as follows:
public string WindowTitle { get; private set; }
public string CurrentUserLoggedIn { get; private set; }
public string CurrentVersion { get; private set; }
No I compile the Project and use dotpeek to decompile the project and see, how it looks like now
public string WindowTitle
{
get
{
return this.\u003CWindowTitle\u003Ek__BackingField;
}
private set
{
if (string.Equals(this.\u003CWindowTitle\u003Ek__BackingField, value, StringComparison.Ordinal))
return;
this.\u003CWindowTitle\u003Ek__BackingField = value;
this.RaisePropertyChanged(nameof (WindowTitle));
}
}
public string CurrentUserLoggedIn
{
get
{
return this.\u003CCurrentUserLoggedIn\u003Ek__BackingField;
}
private set
{
if (string.Equals(this.\u003CCurrentUserLoggedIn\u003Ek__BackingField, value, StringComparison.Ordinal))
return;
this.\u003CCurrentUserLoggedIn\u003Ek__BackingField = value;
this.RaisePropertyChanged(nameof (CurrentUserLoggedIn));
}
}
public string CurrentVersion
{
get
{
return this.\u003CCurrentVersion\u003Ek__BackingField;
}
private set
{
if (string.Equals(this.\u003CCurrentVersion\u003Ek__BackingField, value, StringComparison.Ordinal))
return;
this.\u003CCurrentVersion\u003Ek__BackingField = value;
this.RaisePropertyChanged(nameof (CurrentVersion));
}
}
So RaisePropertyChaned is there.
I have a Crew property, the property has several fields, few of which are Code and InvoiceAmount. The plus button is supposed to insert a new crew into an ObservableCollection of crews. Adding the first item works fine, however when the second item is inserted the first item's code changes to the second item and the second item has no visible code. How do I fix it so that a new crew is inserted every time I click the + button?
Starting UI:
After one item (a) has been added:
Second item (b) has been added:
Here's the ViewModel code:
public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel()
{
AddCrewCommand = new CustomCommand(param => addCrew(), null);
Crews.CollectionChanged += new NotifyCollectionChangedEventHandler(Crews_Updated);
}
private void Crews_Updated(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged("lvCrewList");
}
public Crew Crew { get; set; } = new Crew();
public ObservableCollection<Crew> Crews { get; private set; } = new ObservableCollection<Crew>();
public Crew SelectedCrew { get; set; }
public ICommand AddCrewCommand { get; private set; }
private void addCrew()
{
Crews.Add(Crew);
Crew = new Crew();
}
public ObservableCollection<string> SelectedWorkOrder { get; set; }
}
ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Here's the XAML bit that assigns the Code field:
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<Label Content="Crew" Width="55" Height="25" Margin="10,10,0,0"/>
<TextBox x:Name="txtCrew" Width="75" Height="25" Margin="0,10,10,0"
Text="{Binding Crew.Code, Mode=TwoWay}" />
<Button Content="+" Width="25" Height="25" Margin="0, 10, 0, 0" Command="{Binding AddCrewCommand}" />
</StackPanel>
Crew Class:
public class Crew
{
public string Code { get; set; }
public decimal InvoiceAmount { get; set; } = 0;
public Job Job { get; set; }
public override string ToString() => Code;
}
It is because you are not raising a PropertyChanged event for your Crew property, therefore the textbox is still bound to the previously added crew.
Change your MainPageViewModel.Crew property to the following:
public class MainPageViewModel : ViewModelBase
{
.............
private Crew _crew = new Crew();
public Crew Crew
{
get { return _crew; }
set
{
if (_crew == value) return;
_crew = value;
RaisePropertyChanged(nameof(Crew));
}
}
.......
}
Hi Basically I have a WPF application using the MVVM pattern.
This is my ViewModel:
namespace enLoja.WPF.ViewModel.Relatórios
{
public class SEL_PG_C_ALIViewModel : ViewModelBase
{
private readonly ICAD_EF_C_ALIService _cadEfCAliService;
//Commands
public RelayCommand OnLoaded { get; set; }
public RelayCommand Gerar { get; set; }
public SEL_PG_C_ALIViewModel(ICAD_EF_C_ALIService cadEfCAliService)
{
_cadEfCAliService = cadEfCAliService;
IsDataLoaded = false;
OnLoaded = new RelayCommand(OnLoadedExecute);
Gerar = new RelayCommand(GerarExecute, GerarCanExecute);
}
public async void Load()
{
await Task.Factory.StartNew(() =>
{
IsDataLoaded = true;
RaisePropertyChanged("IsDataLoaded");
});
}
public bool CodigoChecked { get; set; }
public bool DescricaoChecked { get; set; }
public bool IsDataLoaded { get; set; }
#region Commands Execute
public void OnLoadedExecute()
{
Load();
}
public void GerarExecute()
{
var parameters = new Dictionary<string, string>();
if (CodigoChecked)
{
parameters.Add("Order", "Código");
}
if (DescricaoChecked)
{
parameters.Add("Order", "Descrição");
}
IEnumerable<CAD_EF_C_ALI> query = _cadEfCAliService.GetCAD_EF_C_ALI();
var empresaSelecionada = new List<CAD_EF_C_PAR> { ((App)Application.Current).EmpresaSelecionada };
var reportWindow = new REL_PG_C_ALI(query.ToList(), parameters, empresaSelecionada);
reportWindow.ShowDialog();
}
public bool GerarCanExecute()
{
return (IsDataLoaded);
}
#endregion
}
}
And this is my xaml:
<GroupBox x:Name="grbOrdenacao" Header="Ordenação"
Grid.Column="1"
Style="{StaticResource GroupBoxCadastro}" Foreground="#FF333333" BorderBrush="#FF959595" Margin="1,0"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.ColumnSpan="3">
<StackPanel x:Name="SpnOrdem"
Orientation="Horizontal"
VerticalAlignment="Center" Margin="0,-4,0,0">
<RadioButton x:Name="rbnCodigo"
Style="{StaticResource RadioButtonCadastro}"
Content="Código" Margin="5,0" Foreground="#FF333333" FontSize="13"
IsChecked="{Binding CodigoChecked}"/>
<RadioButton x:Name="rbnDescricao"
Style="{StaticResource RadioButtonCadastro}"
Content="Descrição" Margin="20,0,5,0" Foreground="#FF333333" FontSize="13"
IsChecked="{Binding DescricaoChecked}"/>
</StackPanel>
</GroupBox>
My question is: How can I bring the radio-button rbnCodigo already marked as true?
Did you try initializing CodigoChecked to true in the ViewModel constructor?
Ed Plunkett has the correct answer just add the following to your constructor
CodigoChecked = true;
So your constructor should look like this:
public SEL_PG_C_ALIViewModel(ICAD_EF_C_ALIService cadEfCAliService)
{
_cadEfCAliService = cadEfCAliService;
IsDataLoaded = false;
OnLoaded = new RelayCommand(OnLoadedExecute);
Gerar = new RelayCommand(GerarExecute, GerarCanExecute);
CodigoChecked = true;
}