So I have a radio button that I want to change from being unchecked to being checked based on if a button is clicked. So
the XAML code I have is:
<RadioButton GroupName="rdoExchange" Grid.Row="2" Grid.Column="0" x:Name="PauseRadioButton" Command="{Binding PauseCommand}" IsChecked="{Binding Path=check, Mode=TwoWay}" Margin="3"/>
And the View Model Code:
public string check = "True";
public void Reset(object obj)
{
check = "True";
}
private ICommand m_PauseCommand;
public ICommand PauseCommand
{
get
{
return m_PauseCommand;
}
set
{
m_PauseCommand = value;
}
}
private ICommand m_ResetCommand;
public ICommand ResetCommand
{
get
{
return m_ResetCommand;
}
set
{
m_ResetCommand = value;
}
}
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
I've left out the relaycommand code and several other parts that I feel would be irrelevant to solving the problem.
Would something like this work?
XAML:
<RadioButton GroupName="rdoExchange" IsChecked="{Binding Path=OptionOneChecked, Mode=TwoWay}"/>
<Button Command="{Binding ToggleOptionOne}" Height="20" />
View Model:
public class ViewModel: NotificationObject
{
private bool _optionOneChecked;
public bool OptionOneChecked
{
get { return _optionOneChecked; }
set
{
if (value.Equals(_optionOneChecked)) return;
_optionOneChecked = value;
RaisePropertyChanged("OptionOneChecked");
}
}
public ICommand ToggleOptionOne
{
get { return new DelegateCommand(() => OptionOneChecked = !OptionOneChecked); }
}
}
using the NotificationObject class from the PRISM NuGet package.
Related
I want to create a DetailsPage that shows non-editable information where some values are hidden/masked like a password entry with "*****". I would like the user to be able to toggle a button that allows them to see the value. I tried using an Entry control that has a binding to IsPassword with IsReadOnly set to true as follows:
<HorizontalStackLayout>
<Entry Text="{Binding SomeValue}"
IsPassword="{Binding ShowValue}"
IsReadOnly="True"/>
<ImageButton Source="visibility.svg"
Padding="20,0,0,0"
Command="{Binding ToggleValueCommand}"/>
</HorizontalStackLayout>
However, when IsReadOnly is set to true the entry shows the text value even when IsPassword is True
Is this the proper behavior?
If I cannot use an Entry with IsReadOnly="True", then what is the best way to have a Label have this functionality. Should I use a ValueConverter or a Behavior?
As a workaround , you can replace Entry with a Label , change the value while clicking the button each time .
Sample code
Xaml
<HorizontalStackLayout>
<Label Text="{Binding SomeValue}" />
<ImageButton Source="visibility.svg" Padding="20,0,0,0" Command="{Binding ToggleValueCommand}"/>
</HorizontalStackLayout>
code behind
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private bool showValue;
private string someValue;
public string SomeValue
{
get
{
return someValue;
}
set
{
someValue = value;
NotifyPropertyChanged();
}
}
public ICommand ToggleValueCommand { get; set; }
private string copy;
public ViewModel()
{
showValue = true;
SomeValue = "1234";
copy = SomeValue;
ToggleValueCommand = new Command<string>((s) => {
showValue = !showValue;
if (showValue)
{
SomeValue = copy;
}
else
{
SomeValue = "";
for (int i = 0; i < copy.Length; i++)
{
SomeValue += "*";
}
}
});
}
}
I found xamarin render ui is very difficult.
I have a custom view inside the listview which contain a list of small icons. Each item may have some visible icon showing. I realized when i scrolled down to bottom and scroll back to the top, the one supposed to have that icon to be shown was not shown. I passed in an object into the custom view to tell which one to be displayed.
Item in listview, local:ChildInfoIconsView is the custom view.
<StackLayout Orientation="Vertical"
Grid.Row="0"
Grid.Column="1"
VerticalOptions="Center"
HorizontalOptions="Start">
<Label AutomationId="aChildName" Style="{StaticResource MediumBoldFont}" x:Name="childName" Text="{Binding DisplayName}" HorizontalOptions="StartAndExpand" />
<local:ChildInfoIconsView
Child="{Binding .}"
VerticalOptions="Fill">
</local:ChildInfoIconsView>
</StackLayout>
Main Code for custom view
public partial class ChildInfoIconsView : ContentView
{
public static readonly BindableProperty OrientationProperty = BindableProperty.Create(nameof(Orientation), typeof(StackOrientation), typeof(StackOrientation), StackOrientation.Vertical, BindingMode.OneWay, null);
public static readonly BindableProperty ShowClassroomProperty = BindableProperty.Create(nameof(ShowClassroom), typeof(bool), typeof(bool), true, BindingMode.OneWay, null);
public static readonly BindableProperty ChildProperty = BindableProperty.Create(nameof(Child), typeof(ChildModel), typeof(ChildModel), null, BindingMode.OneWay, null);
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName.Equals(nameof(Child)))
{
if (Child != null)
{
this.ImageUnauth.IsVisible = (Child.HasUnauthorized.HasValue) ? Child.HasUnauthorized.Value : false;
this.ImageMedical.IsVisible = (Child.HasMedical.HasValue) ? Child.HasMedical.Value : false;
this.ImageBirthday.IsVisible = Child.IsBirthday;
this.ImageNewChild.IsVisible = !string.IsNullOrEmpty(Child.NewChildFlagImage);
this.ImageClassroom.IsVisible = (!ShowClassroom) ? false : !string.IsNullOrEmpty(Child.Classroom);
this.textClass.Text = Child.Classroom;
this.textClass.IsVisible = (!ShowClassroom) ? false : !string.IsNullOrEmpty(Child.Classroom);
}
}
else if (propertyName.Equals(nameof(ShowClassroom)))
{
this.ImageClassroom.IsVisible = ShowClassroom;
this.textClass.IsVisible = ShowClassroom;
}
else if (propertyName.Equals(nameof(Orientation)))
{
this.layout.Orientation = Orientation;
}
}
public ChildInfoIconsView()
{
InitializeComponent();
}
public StackOrientation Orientation
{
get
{
return (StackOrientation)GetValue(OrientationProperty);
}
set
{
SetValue(OrientationProperty, value);
}
}
public bool ShowClassroom
{
get
{
return (bool)GetValue(ShowClassroomProperty);
}
set
{
SetValue(ShowClassroomProperty, value);
}
}
public ChildModel Child
{
get
{
return (ChildModel)GetValue(ChildProperty);
}
set
{
SetValue(ChildProperty, value);
}
}
It work fine when using old version of xamarin.forms. When updated the package, this happen on android.
I am have an app that basically loads a bunch of ContentViews into the home ContentPage. I THINK there is a problem here because all of the viewmodels would essentially need to been initialized every time we load the home page. I am wondering if it is worth my time to ditch the below code and convert the views from ContentView's to ContentPage's and just do Navigation.PushAsync(new View1()); instead. Sorry I know this is alot of example code but I would really like to get a clear picture of best practice.
My Home.xaml
<Grid x:Name="ContentBody" VerticalOptions="FillAndExpand">
<local:View1 Grid.Row="0" x:Name="View1" IsVisible="{Binding View1IsVisible}" BindingContext="{Binding View1ViewModel}" />
<local:View2 Grid.Row="0" x:Name="View2" IsVisible="{Binding View2IsVisible}" BindingContext="{Binding View2ViewModel}" />
<local:View3 Grid.Row="0" x:Name="View3" IsVisible="{Binding View3IsVisible}" BindingContext="{Binding View3ViewModel}" />
<local:View4 Grid.Row="0" x:Name="View4" IsVisible="{Binding View4IsVisible}" BindingContext="{Binding View4ViewModel}" />
<local:View5 Grid.Row="0" x:Name="View5" IsVisible="{Binding View5IsVisible}" BindingContext="{Binding View5ViewModel}" />
<local:View6 Grid.Row="0" x:Name="View6" IsVisible="{Binding View6IsVisible}" BindingContext="{Binding View6ViewModel}" />
<local:DrawerView Grid.Row="0" x:Name="DrawerView" IsVisible="{Binding DrawerViewIsVisible}" />
</Grid>
Then In my HomeViewModel...
private readonly View1ViewModel _view1ViewModel = new View1ViewModel();
public View1ViewModel View1ViewModel { get { return _view1ViewModel; } }
private readonly View2ViewModel _view2ViewModel = new View2ViewModel();
public View2ViewModel View2ViewModel { get { return _view2ViewModel; } }
private readonly View3ViewModel _view3ViewModel = new View3ViewModel();
public View3ViewModel View3ViewModel { get { return _view3ViewModel; } }
private readonly View4ViewModel _view4ViewModel = new View4ViewModel();
public View4ViewModel View4ViewModel { get { return _view4ViewModel; } }
private readonly View5ViewModel _view5ViewModel = new View5ViewModel();
public View5ViewModel View5ViewModel { get { return _view5ViewModel; } }
private readonly View6ViewModel _view6ViewModel = new View6ViewModel();
public View6ViewModel View6ViewModel { get { return _view6ViewModel; } }
///////////////////Some Visibility Properties...//////////////////////
///////////////////Some Visibility Properties...//////////////////////
private bool _view1IsVisible;
public bool View1IsVisible
{
get { return _view1IsVisible; }
set { _view1IsVisible = value; OnPropertyChanged("View1IsVisible"); }
}
private bool _view2IsVisible;
public bool View2IsVisible
{
get { return _view2IsVisible; }
set { _view2IsVisible = value; OnPropertyChanged("View2IsVisible"); }
}
private bool _view3IsVisible;
public bool View3IsVisible
{
get { return _view3IsVisible; }
set { _view3IsVisible = value; OnPropertyChanged("View3IsVisible"); }
}
private bool _view4IsVisible;
public bool View4IsVisible
{
get { return _view4IsVisible; }
set { _view4IsVisible = value; OnPropertyChanged("View4IsVisible"); }
}
private bool _view5IsVisible;
public bool View5IsVisible
{
get { return _view5IsVisible; }
set { _view5IsVisible = value; OnPropertyChanged("View5IsVisible"); }
}
private bool _view6IsVisible;
public bool View6IsVisible
{
get { return _view6IsVisible; }
set { _view6IsVisible = value; OnPropertyChanged("View6IsVisible"); }
}
/////And then this is more or less a method to show the view/////////////
private void ShowView(ViewChangedEventArgs e)
{
HideAllViews();
switch(e.SelectedView){
case ViewType.View1:
View1IsVisible = true
break;
case ViewType.View2:
View2IsVisible = true
break;
case ViewType.View3:
View3IsVisible = true
break;
case ViewType.View4:
View4IsVisible = true
break;
case ViewType.View5:
View5IsVisible = true
break;
case ViewType.View6:
View6IsVisible = true
break;
}
}
Can someone tell me if this approach is fine? as using this approach everytime I add a new page I will need to add a view to the Homepage view and the viewModel & IsVisible properties to the Homepage ViewModel..
I would greatly appreciate any guidance on this. I think a better approach would be to just seperate the ContentViews from the HomePage and when I Navigate to one of these views I would just PushAsync. I have seen supporting documentation online where some people are taking the above approach, I am just trying to ask the experts what they think when they see this code.
After speaking w/ a member of the Xamarin team I've been told to remove all the views from this homeview page, bind the perspective view models in their own code behinds, and from there I can navigation using Navigation.PushAsync(new View1());
Tutorial:
https://github.com/XamarinUniversity/XAM290
Documentaiton:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/enterprise-application-patterns/
I have a combobox displaying the lists within it perfectly in the ViewModel but I'm looking to have it so that when a selected item from the list is chosen it fires the ViewModel screen and I only want one from the list to do this?
So here is what I have in the ChooseView:
<ComboBox x:Name="CatalogName1" SelectedItem="{Binding SelectedCatalog1}" Style="{DynamicResource appComboBox}" Grid.Row="1" Grid.Column="1" >
</ComboBox>
and in the ChooseViewModel:
public List<string> CatalogName1
{
get
{
return new List<string> { "New", "Replace", "Extended", "Nothing", "ShowScreen" };
}
}
private string selectedCatalog1;
public string SelectedCatalog1
{
get
{
return this.selectedCatalog1;
}
set
{
this.selectedCatalog1 = value;
this.NotifyOfPropertyChange(() => this.SelectedCatalog1);
}
}
the "ShowScreen" in the combo list should display the ShowScreenViewModel but I have tried with the getter setter and it's not making sense to me
Okay, this is the way I would fix the problem...
private string selectedCatalog1;
public string SelectedCatalog1
{
get
{
return selectedCatalog1;
}
set
{
selectedCatalog1 = value;
ValidateValue(value);
NotifyOfPropertyChange(() => SelectedCatalog1);
}
}
private void ValidateValue(string s)
{
if (s == "ShowScreen")
{
ActivateItem(new ShowScreenViewModel());
}
}
I'd like to RaiseCanExecuteChanged when CanExecute condition got changed.
E.g.:
public class ViewModel
{
public viewModel()
{
Command = new RelayCommand(action,condition);
}
private bool condition()
{
return this.Condition1&&this.Condition2&&this.Condition3;
}
public bool Condition1
{
get{...}
set{.... **command.RaiseCanExecuteChanged();}**
}
public bool Condition2
{
get{...}
set{.... command.**RaiseCanExecuteChanged();}**
}
public bool Condition3
{
get{...}
set{.... **command.RaiseCanExecuteChanged();}**
}
}
That works fine.
But I don't like to write so many RaiseCanExecuteChanged, I want to set these changes automatically.
E.g
In RelayCommand, create a new method named RaiseChanged
public void RaiseChanged(XXXXXX XXX, params string[] propertyNames)
{
// for each property in propertyNames,
// RaiseCanExecuteChanged();
}
I put ViewModel vm as the parameters, and use vm.PropertyChanged+=(s,e)=>{}
But I don't think it's a good way to do this.
Does anyone have other ideas?
I develop my solution where I can do like that:
C# View Model:
public bool CanExecuteMethod(object sender)
{
}
public void ButtonExecuteMethod(object sender)
{
}
public event Action EventNotifyCanExecuteChanged;
private Action _DelegateNotifyCanExecuteChanged;
public Action DelegateNotifyCanExecuteChanged
{
get { return _DelegateNotifyCanExecuteChanged; }
set { _DelegateNotifyCanExecuteChanged = value; }
}
public void CanExecuteFlag
{
if (EventNotifyCanExecuteChanged != null) { EventNotifyCanExecuteChanged(); }
if (_DelegateNotifyCanExecuteChanged != null) { _DelegateNotifyCanExecuteChanged();}
}
XAML:
< Button Content="Button Cmd-ExCeCh" HorizontalAlignment="Left" Margin="27,231,0,0"
VerticalAlignment="Top" Width="120"
Command="{mark:BindCommandResource MainWindowViewModel,
ExecuteMethodName=ButtonExecuteMethod,
CanExecuteMethodName=CanExecuteMethod,
EventToInvokeCanExecuteChanged=EventNotifyCanExecuteChanged,
PropertyActionCanExecuteChanged=DelegateNotifyCanExecuteChanged}" />
I put/share this solution in my open source project MVVM-WPF XAML Mark-up Binding Extensions - http://wpfmvvmbindingext.codeplex.com