label Hide and show using xaml and mvvvm - c#

How to Lable Hide and show if admin is login then one label is displayed otherwise label is hidden {How Solve it} ?
xaml Code
<StackLayout IsVisible="{Binding IsAdminTrue}">
<Label Text="is_professional"></Label>
</StackLayout>
ViewModel Code
public void IsProfessional()
{
if (CurrentUser.IsAdmin!= true)
{
IsAdminTrue= false;
}
else
{
IsAdminTrue= true;
}
}

public void IsProfessional()
{
if (CurrentUser.IsAdmin!= true)
{
lblNo.Visibility= Visibility.Visible;
}
else
{
lblNo.Visibility = Visibility.Hidden;
}
}
Here lblNo is an label.

You should set the Visibility property on the Label, not the StackLayout. You could either change IsAdminTrue to IsAdminVisible (of type Visibility), or you could use the BooleanToVisibility converter. Second option is usually the preferred method.
Of course, none of this will matter if IsAdminTrue doesn't raise PropertyChanged.

Related

Xamarin Forms - Recognize Postition

I want to make a comment entry that is only visible if the user is at the bottom of the article.
So the app has to recognize when the user has scrolled enough, then a method should make the entryfield visible.
I can't find something like this on the Internet, so maybe you guys can help me.
This one is without the entryfield and when the user scrolls down ...
... the entryfield becomes visible
If you are using a ScollView, there is a Scrolled event that fires whenever the view is scrolled and the ScrolledEventArgs contain ScrollX and ScrollY properties that allow you to know where the ScrollView currently is. If you compare ScrollY to the height of the ContentSize property of the ScrollView, e.g.:
XAML:
<StackLayout>
<ScrollView x:Name="scrollView" Scrolled="Handle_Scrolled">
<StackLayout>
<Label Text="{Binding Article}" HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand" />
</StackLayout>
</ScrollView>
<Entry IsVisible="{Binding AtEnd}" Placeholder="End reached!" />
</StackLayout>
Code behind (MainPage is a ContentPage subclass):
string _article;
public string Article
{
get
{
return _article;
}
set
{
if (_article != value)
{
_article = value;
OnPropertyChanged("Article");
}
}
}
bool atEnd;
public bool AtEnd
{
get
{
return atEnd;
}
set
{
if (atEnd != value)
{
atEnd = value;
OnPropertyChanged("AtEnd");
}
}
}
public MainPage()
{
Article = "<put in enough text here to force scrolling>";
AtEnd = false;
InitializeComponent();
BindingContext = this;
}
void Handle_Scrolled(object sender, Xamarin.Forms.ScrolledEventArgs e)
{
if (e.ScrollY + scrollView.Height >= scrollView.ContentSize.Height)
AtEnd = true;
else
AtEnd = false;
}
That said, why not just put the entry below the article using the same scroll view? IOW just put the Entry element after the Label above in the same StackLayout and the Entry will just be there at the end always, but the user won't see it until they scroll down. Seems that that would be a simpler solution. Of course you may not be using a Label but the same applies, just put the Entry at the bottom of the layout that the ScrollView is scrolling.

Change buttons BackgroundColor using MVVM

I have two buttons, When I am clicking on one button I want to change another button BackgroundColor using mvvm
I am trying to make it like this
<StackLayout>
<Button Text="Red" BackgroundColor="Accent" Command="{Binding ChangeButtons}" x:Name="btnRed"></Button>
<Button Text="Blue" x:Name="btnBlue"></Button>
</StackLayout>
When I click on btnRed I want btnBlue BackgroundColor to be changed.
ModelView page
public class ButtonColorViewModel
{
public Command ChangeButtons
{
get
{
return new Command(() => {
//Change here button background colors
});
}
}
}
How can I implement it?
Basically like this, you need a color property to bind to. You can change the value of the property in your command. You can adjust it to suit your needs,2,3, colors/buttons etc.:
public class ButtonColorViewModel
{
public Command ChangeButtons
{
get
{
return new Command(() => {
//Change here button background colors
BackgroundColorBtn1 = Color.Green; //or something
});
}
}
private _backgroundColorBtn1 = Color.White;
public Color BackgroundColorBtn1
{
get { return _backgroundColorBtn1;}
set
{
if (value == _backgroundColorBtn1)
return;
_backgroundColorBtn1 = value;
NotifyOnPropertyChanged(nameof(BackgroundColorBtn1));
}
}
}
With XAML:
<StackLayout>
<Button Text="Red" BackgroundColor="Accent" Command="{Binding ChangeButtons}"
x:Name="btnRed"></Button>
<Button BackgroundColor="{Binding BackgroundColorBtn1}" Text="Blue"
x:Name="btnBlue"></Button>
</StackLayout>
The best option, depending on your thought about MVVM, is to avoid (as much as possible) using UI inside ViewModel.
In the previous answer, the color object is used.
If you want to keep MVVM in this case:
create a property with OnPropertyChanged like maybe an enum
Bind it to background color button
Use a converter to convert your property into background color :)
I know it's more stuff but it's more MVVM like.
Also, if you stay only in UI, go to code behind.
Use click and manage the background color directly.

One databinding prevents other from working

I have a textblock that is a 'status label'. I want this label to be updated, and when that happens, I want its color to be also set automatically - as well as visibility (Label invisible until it has content).
The problem is, that if I specify anything more than the text binding, then the textblock does not change (i.e. text does not appear, and it is still hidden).
Actually, I tried also without binding visibility, and it appears that the Foreground also blocks the binding.
<TextBlock x:Name="StatusInfo"
HorizontalAlignment="Center" VerticalAlignment="Bottom"
FontSize="9"
Visibility="{Binding ElementName=ThisUc,
Path=StatusLabelVisibility}"
Text="{Binding ElementName=ThisUc,
Path=StatusLabel}"
Foreground="{Binding ElementName=ThisUc,
Path=StatusLabelBrush}" />
This is all in a UserControl, so I am using dependency properties for StatusLabel property, as I want to bind it to properties in main window... Foreground and Visibility properties are not dependency properties, as I don't want to expose them.
This is my property setter and getter:
public string StatusLabel
{
get { return (string)GetValue(StatusLabelProperty); }
set
{
SetValue(StatusLabelProperty, value);
RaisePropertyChanged("StatusLabel");
if (value != string.Empty)
{
StatusLabelVisibility = System.Windows.Visibility.Visible;
if (value.HasAny("success", "ok") && !value.HasAny("partial"))
{
StatusLabelBrush = Brushes.Green;
}
else if (value.HasAny("fail"))
{
StatusLabelBrush = Brushes.DarkRed;
}
else if (value.HasAny("partial"))
{
StatusLabelBrush = Brushes.DarkGoldenrod;
}
else
{
StatusLabelBrush = Brushes.Black;
}
}
else
{
StatusLabelVisibility = System.Windows.Visibility.Collapsed;
}
}
}
Please let me know what am I doing wrong, perhaps that's not the way to go altogether?
Cheers
====================
While Meredith's answer solved the issue, let me just post a comment for future reference (as it was not obvious for me):
Here it goes - if you assign the UserControl property directly, not via property binding, it appears to lose the 'bound' - and if you try to change the bound property again, it won't update the control as it would have before it 'lost the bound'
Cheers
If StatusLabel is a DependencyProperty, you can't put anything else in the setter - it won't get called correctly. Look up the way to do changed events for DependencyProperties instead. You need a PropertyChangedCallback. Check out How to use PropertyChangedCallBack. Raise your prop changes, and set all the other properties in the callback.

Changing isVisible property of Xamarin Forms XAML buttons

I am trying to dynamically show/hide button inside Xamarin Forms ContentPage.
I have two buttons in my XAML code:
<StackLayout Orientation="Vertical">
<Button x:Name="start_btn" Clicked="startPanic">
<Button.Text>START</Button.Text>
</Button>
<Button x:Name="stop_btn" IsVisible="false">
<Button.Text>STOP</Button.Text>
</Button>
</StackLayout>
Corresponding C# code:
public partial class PanicPage : ContentPage
{
private Button startBtn;
private Button stopBtn;
public PanicPage ()
{
InitializeComponent ();
startBtn = this.FindByName<Button> ("start_btn");
stopBtn = this.FindByName<Button> ("stop_btn");
}
private void startPanic(object sender, EventArgs args){
Device.BeginInvokeOnMainThread (() => {
startBtn.IsVisible = false;
stopBtn.IsVisible = true; // DOESN'T WORK, button still will be hidden
});
}
}
When I set isVisible property in XAML, it doesn't react for any property change in event method (startPanic). How can I fix it?
Change your code in xmal file and write properties for start and stop button
<Button x:Name="start_btn" Clicked="startPanic" IsVisible="{Binding IsStartVisible}">
<Button.Text>START</Button.Text>
</Button>
<Button x:Name="stop_btn" IsVisible="{Binding IsStopVisible}">
<Button.Text>STOP</Button.Text>
</Button>
In ViewModel write following property and similar for start button and set IsStopVisible =true/false based on your logic
private bool _isStopVisible;
public bool IsStopVisible{
get {
return _isStopVisible;
}
set {
_isStopVisible= value;
RaisePropertyChanged ("IsStopVisible");
}
}
Maybe I'm late but I was searching this too without success. This may be useful for someone.
objectView.SetValue(IsVisibleProperty, false); // the view is GONE, not invisible
objectView.SetValue(IsVisibleProperty, true);
It should work just fine. I copied your code and cleaned it up a bit, it shows the STOP button, then I
A few remarks:
use the short property where possible <Button Text="X"/>, it's
easier to read
when you add a XAML page the IDE adds a .xaml.cs file next to it and generates another .g.cs that you don't see. The .g.cs file
contains generated code that finds all the x:Name'd elements and
defines placeholders for them, no need to find them by name yourself
all UI-initiated events are executed on the UI thread, no need to do that explicitly
Here's the XAML, same as yours just tighter and added Margin so the button is visible
<StackLayout Orientation="Vertical" Margin="20">
<Button x:Name="start_btn" Clicked="startPanic" Text="START" />
<Button x:Name="stop_btn" Text="STOP" IsVisible="false" />
</StackLayout>
And the code behind:
public partial class TestPage : ContentPage
{
public TestPage ()
{
InitializeComponent ();
}
private void startPanic(object sender, EventArgs args){
Device.BeginInvokeOnMainThread (() => {
start_btn.IsVisible = false;
stop_btn.IsVisible = true;
});
}
}
Use the Visibility property of view.
for example if u want to make your button invisible you can do
if(condition)
{
button.Visibility=ViewStates.Invisible;
}
else
{
button.Visibility=ViewStates.Visible;
}

How can I make a RichTextBox scroll to the end when I add a new line?

I have several read only RichTextBox's that are used for logging output. Since they're read only they don't seem to automatically scroll when the text is updated. I can use the TextChanged event to force a scroll to end, but is there not simply a way to set a property or something in the XAML so that scrolling happens like normal?
I had googled for your problem and found this post.
In the section "Programming the RichTextBox" author had described about getting the behavior what you had been expecting.
Please check and let me know if it is of any use.
I tried to reproduce your problem and came up with the following solution
<Window x:Class="CheckRichTextBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="170" Width="300">
<StackPanel>
<RichTextBox Height="100" Name="richTextBox1" IsReadOnly="True" VerticalScrollBarVisibility="Visible"/>
<Button Name="btnAdd" Content="Click me to add text" VerticalAlignment="Bottom" Click="BtnAddClick" />
</StackPanel>
</Window>
The code behind for the same is as below:
using System.Windows;
namespace CheckRichTextBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnAddClick(object sender, RoutedEventArgs e)
{
richTextBox1.AppendText("You had Clicked the button for adding text\n");
richTextBox1.ScrollToEnd();
}
}
}
This solves the problem of autoscroll, please check it and let me know if it is of any help.
I solved this problem using an Interactivity trigger and a very simple action.
The action looks like this:
public class ScrollToBottomAction : TriggerAction<RichTextBox>
{
protected override void Invoke(object parameter)
{
AssociatedObject.ScrollToEnd();
}
}
Then in my XAML I have this:
<RichTextBox IsReadOnly="True" VerticalScrollBarVisibility="Auto">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<interactivity:ScrollToBottomAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</RichTextBox>
I came up with the following solution for wpf richtextbox autoscroll
public partial class MainWindow
{
private bool AutoScroll = true;
public MainWindow()
{
InitializeComponent();
yourRichTextBox.Loaded += (s, e) =>
{
var scrollViewer = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(yourRichTextBox, 0), 0) as ScrollViewer;
scrollViewer.ScrollChanged += (scroller, eScroller) => ScrollViewer_ScrollChanged(scroller, eScroller);
};
}
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
// User scroll event : set or unset autoscroll mode
if (e.Source as ScrollViewer != null && e.ExtentHeightChange == 0)
{ // Content unchanged : user scroll event
if ((e.Source as ScrollViewer).VerticalOffset == (e.Source as ScrollViewer).ScrollableHeight)
{ // Scroll bar is in bottom
// Set autoscroll mode
AutoScroll = true;
}
else
{ // Scroll bar isn't in bottom
// Unset autoscroll mode
AutoScroll = false;
}
}
// Content scroll event : autoscroll eventually
if (AutoScroll && e.ExtentHeightChange != 0 && e.Source as ScrollViewer != null)
{ // Content changed and autoscroll mode set
// Autoscroll
(e.Source as ScrollViewer).ScrollToVerticalOffset((e.Source as ScrollViewer).ExtentHeight);
}
}
}
This is how to do it in C#
Put the RichTextBox in a ScrollViewer like this:
scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
scrollViewer.Content = rTextBox;
Then add the scrollViewer to the Grid or whatever you are using.
RootGrid.Children.Add(scrollViewer);
(This is in C# but could all be done in XAML as well.)
Then use C# code like this to make it scroll to the bottom when you add text:
rTextBox.AppendText(str);
scrollViewer.ScrollToEnd();
Hope that helps.
RichTextBox.AppendText("String")
RichTextBox.ScrollToCaret()
When I was adding to RichTextBox.text, ScrollToCaret() does not work.
RichTextBox.text = RichTextBox.text + "String"
RichTextBox.ScrollToCaret()

Categories