I have below xaml for "canvas"...i want to change its visibility depends on property change.
XAML:
<d1:BooleanToVisibilityConverter x:Key="BoolToVis" />
Visibility="{Binding Path=IsVisible, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
I have this Visibility property in ViewModel
private bool _isVisible;
public bool IsVisible
{
get { return _isVisible; }
set
{
_isVisible = value;
RaisePropertyChanged("IsVisible");
}
}
This is my Converter code:
class BooleanToVisibilityConverter : IValueConverter
{
public BooleanToVisibilityConverter() { }
#endregion
#region Properties
public bool Collapse { get; set; }
#endregion
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool bValue = (bool)value;
if (bValue)
{
return Visibility.Visible;
}
else
{
return Visibility.Collapsed;
//if (Collapse)
// return Visibility.Collapsed;
//else
// return Visibility.Hidden;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//Visibility visibility = (Visibility)value;
//if (visibility == Visibility.Visible)
// return true;
//else
// return false;
return value;
}
#endregion
}
While debugging I observed my Setter is changing the property value but its not hitting break point on my converter. Converter is getting hit only initially while loading window. After that it doesnt get triggered even though property is changed.
I read that you are using Prism so try to change your RaisePropertyChanged in this form:
RaisePropertyChanged(() => IsVisible);
Related
I need help as i've a UserControl, "myUC" and i want change its visibility when i press a MenuItem. I've following class BoolToVisibilityConverter :
[ValueConversion(typeof(bool), typeof(Visibility))]
public sealed class BoolToVisibilityConverter : IValueConverter
{
public Visibility TrueValue { get; set; }
public Visibility FalseValue { get; set; }
public BoolToVisibilityConverter()
{
// set defaults
TrueValue = Visibility.Visible;
FalseValue = Visibility.Collapsed;
}
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
if (!(value is bool))
return null;
return (bool)value ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
if (Equals(value, TrueValue))
return true;
if (Equals(value, FalseValue))
return false;
return null;
}
}
I am setting my converter as StaticResource in Windows.Resource
<Window.Resources>
<vs:BoolToVisibilityConverter x:Key="VisibilityConverter" TrueValue="Visible" FalseValue="Hidden" />
</Window.Resources>
And i've added converter when i call user control in XAML
<uc:Add Visibility="{Binding MyProperty,Converter={StaticResource VisibilityConverter},FallbackValue=Hidden}" />.
I've binding on the property " MyProperty" so:
private bool _myProperty;
public bool MyProperty
{
get {
return _myProperty;
}
set {
if (_myProperty== true)
_myProperty= value;
else
_myProperty= true;
OnPropertyChanged("MyProperty");
}
}
But when i launch the application, it does not change the visibility of UserControl.
I forgot to mention that i've the MenuItem bindig with ICommand
<MenuItem Name="mnuAggiungi" Header="_Aggiungi" Command="{Binding MyCommand}"/>
RelayCommand _add;
public ICommand MyCommand
{
get
{
if (_add == null) _add = new RelayCommand(param => this.MyCommandUC());
return _add;
}
}
public void MyCommandUC()
{
}
I forgot to mention that i've the MenuItem bindig with ICommand
MenuItem Name="mnuAggiungi" Header="_Aggiungi" Command="{Binding MyCommand}"
RelayCommand _add;
public ICommand MyCommand
{
get
{
if (_add == null) _add = new RelayCommand(param => this.MyCommandUC());
return _add;
}
}
public void MyCommandUC()
{
}
in command handler MyCommandUC do this..
public void MyCommandUC
{
MyProperty = false; // for hidden
}
but saying this I would want to tell you that, your code is quite confusing, sometimes you set visibility to Hidden sometimes you set it to Collapsed, also, you try to set truevalue and FalseValues from xaml but your converter has hard coded values in its constructor there by making it useless to set anything from xaml
--- edit
I just saw this .. and I.. !
set {
if (_myProperty== true)
_myProperty= value;
else
_myProperty= true;
OnPropertyChanged("MyProperty");
}
change above code to
set {
_myProperty= value;
OnPropertyChanged("MyProperty");
}
Value of MyProperty change when click on MenuItem, and i capture click with ICommand. I've think to do so
_private bool _myProperty;
...
set
{ _
myProperty = value;
}
}
public void MyCommandUC()
{
if (MyProperty == false)
MyProperty = true;
else
MyProperty = false;
}
but don't work
I am new to WPF and am a little lost.
I want to display Text within a label binding it to the following class:
class Status
{
public string Message;
public bool Success;
}
I want the label to display the "message" in green if success and in red if not. I am not sure how to start on it.
First, you need to bind to properties, not members. You should also get into the habit of implementing INotifyPropertyChanged on your class that you're binding to.
public class Status : INotifyPropertyChanged
{
private string message;
public string Message
{
get { return this.message; }
set
{
if (this.message == value)
return;
this.message = value;
this.OnPropertyChanged("Message");
}
}
private bool success;
public bool Success
{
get { return this.success; }
set
{
if (this.success == value)
return;
this.success = value;
this.OnPropertyChanged("Success");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
In terms of binding, you'd have to use a custom IValueConverter
public class RGColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
bool success = (bool) value;
return success ? Brushes.Green : Brushes.Red;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And the relevant binding/setup
<Window.Resources>
<wpfApplication2:RGColorConverter x:Key="colorConverter" />
</Window.Resources>
<Label Content="{Binding Message}" Foreground="{Binding Success, Converter={StaticResource colorConverter}}" />
In my application I have 3 data grids in a single xaml file. Based on the User selection I want show one grid and hide other grids.
in my view model class I have Boolean property for each grid and based on the selection I am setting it to true or false.But all grids are visible .
<DataGrid Visibility="{Binding Path=IsGridVisible}" >
In my view model I am setting IsGridVisible value
public bool IsCapexGridVisible
{
get { return isCapexGridVisible; }
set { isCapexGridVisible = value; RaisePropertyChangedEvent("IsCapexGridVisible"); }
}
Please provide your ideas. Thanks
There is a BooleanToVisibilityConverter available to you that converts true to System.Windows.Visibility.Visible and false to System.Windows.Visibility.Collapsed.
So you can take help of this pre built converter and must add it to resources.
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
Create a property of type bool in your ViewModel
bool _dgVisibility;
public bool DataGridVisibility
{
get { return _dgVisibility; }
set
{
_dgVisibility = value;
OnPropertyChanged("DataGridVisibility");
}
}
and you can use it as below
<DataGrid Visibility="{Binding Path=DataGridVisibility, Converter={StaticResource BoolToVis}}"/>
Visibility property on UIElement is not a boolean. It is an enum with three values:
Collapsed Do not display the element, and do not reserve space for it in layout.
Hidden Do not display the element, but reserve space for the element in layout.
Visible Display the element.
So in order to set it properly from ViewModel you should:
- make your property type of Visibility (not best solution in the world)
- Use converter for the binding which will do the trick of translating boolean to visibility
public class BooleanToCollapsedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType == typeof(Visibility) && value is bool)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
throw new FormatException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Additional converter variant with visibility customization
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
[MarkupExtensionReturnType(typeof(IValueConverter))]
public class BoolToVisibilityConverter : MarkupExtension, IValueConverter
{
[ConstructorArgument("TrueValue")]
public Visibility TrueValue { get; set; }
[ConstructorArgument("FalseValue")]
public Visibility FalseValue { get; set; }
[ConstructorArgument("NullValue")]
public Visibility NullValue { get; set; }
public BoolToVisibilityConverter()
{
TrueValue = Visibility.Visible;
FalseValue = Visibility.Collapsed;
NullValue = Visibility.Collapsed;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return NullValue;
if (value is not bool boolValue)
return null;
return boolValue ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (Equals(value, TrueValue))
return true;
if (Equals(value, FalseValue))
return false;
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
Usage:
<someControl ...
xmlns:converters="clr-namespace:ExampleNamespace.Converters;assembly=ExampleAssembly"
...
>
...
Visibility="{Binding IsSearchInProgress,
Mode=OneWay,
Converter={converters:BoolToVisibilityConverter}}"
Visibility="{Binding IsSearchInProgress,
Mode=OneWay,
Converter={converters:BoolToVisibilityConverter TrueValue=Collapsed, FalseValue=Visible}}"
I have a textblock inside a list view that I need to hide or collapse when it is empty or null. I tried using a string converter but that does not do it.
Any other ideas?
Update # 1:
Here is the code inside the textblock:
Visibility="{Binding Converter={StaticResource StringConverter}}
Here is the converter:
public class StringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return string.IsNullOrEmpty(value.ToString()) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
I would recommend creating text and visibility bindings on your textbox.
Here's an example of the view model properties you'd have.
public String TextBoxText
{
get { return textBoxText; }
set
{
if (value != textBoxText)
{
textBoxText= value;
SetTextBoxVisibility();
OnPropertyChanged("TextBoxText");
}
}
}
private String textBoxText;
public Visibility TextBoxVisibility
{
get { return textBoxVisibility; }
set
{
if (value != textBoxVisibility)
{
textBoxVisibility= value;
OnPropertyChanged("TextBoxVisibility");
}
}
}
private Visibility textBoxVisibility;
public void SetTextBoxVisibility()
{
this.TextBoxVisibility = String.IsNullOrEmpty(this.TextBoxText) ? Visibility.Collapsed : Visibility.Visible;
}
The only thing you've not shown of your code is where you instantiate the converter class. Is this because you're not doing so?
Typically you'd add something like this to app.xaml:
<Application.Resources>
<ResourceDictionary>
<conv:StringConverter x:Key="StringConverter " />
</ResourceDictionary>
</Application.Resources>
I take one grid in silverlight. Initially textbox2 is invisible. When I click on textbox1 we have to visible textbox2. I try it as belows:
<TextBox x:Name="textbox1" SelectionChanged="txt1_SelectionChanged"/>
<TextBox x:Name="textbox2 " Visibility="Collapsed"/>
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
textbox2 .Visibility = Visibility.Visible;
}
It works fine.
But I want to use MVVM pattern. So there I don't want to use eventHandler.
So how to do that using MVVM pattern?
edit: sorry, i thought you meant the textbox to be visible when the other one has focus, I changed my inital answer.
I can not try it at the moment, but you bind the Visibility property of your textbox to the SelectionLength property of the other, using a valueconverter:
<UserControl.Resources>
<local:IntToVisibilityConverter x:Key="IntToVisibilityConverter" />
</UserControl.Resources>
<Textbox
x:name="textbox2"
Visibility={Binding SelectionLength,
ElementName="textbox1"
Converter={StaticResource IntToVisibilityConverter}}
/>
implement the value converter like this:
public class IntToVisibilityConverter : IValueConverter
{
public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
{
return (int)value > 0 ? Visibility.Visible : Visibility.Hidden;
}
public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture)
{
throw new InvalidOperationException("Converter cannot convert back.");
}
}
Create a property in viewmodel
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
if (_isVisible == value)
{
return;
}
_isVisible = value;
RaisePropertyChanged("IsVisible");
}
}
This returns a boolean value so u need a converter BoolToVisibility Converter make BoolToVisibilityConverter class
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter == null)
{
return ((bool)value == true) ? Visibility.Visible : Visibility.Collapsed;
}
else if (parameter.ToString() == "Inverse")
{
return ((bool)value == true) ? Visibility.Collapsed : Visibility.Visible;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
Now Bind the TextBox and use the converter
<UserControl.Resources>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</UserControl.Resources>
<Textbox x:name="textbox2" Visibility={Binding IsVisible,
Converter={StaticResource BoolToVisibilityConverter}}/>
This is it.
The biggest problem you will have is getting the SelectionChanged event sent to the ViewModel. Commands in SL4 only work on button clicks, so TextBox SelectionChanged events can't fire commands by default.
There are a few solutions out there for you:
Binding Commands to ANY event
EventToCommand Behavior
Once you have done that, you can have a command in your ViewModel that sets a Visibility property in your ViewModel and fires the PropertyChanged event.
Using my ViewModelSupport library, the VM would look like this:
public class MyViewModel : ViewModelBase
{
public Visibility ShowTextbox2
{
get { return Get(() => ShowTextbox2, Visibility.Collapsed); }
set { Set(() => ShowTextbox2, value); }
}
public void Execute_SelectionChanged()
{
ShowTextbox2 = Visibility.Visible;
}
}
}
You would then bind the SelectionChanged event to the SelectionChanged command in the VM and the Textbox2 visibility attribute to the ShowTextbox2 property in the VM.
Good luck.
If you are using MVVM Light, you can also do it like this:
using System.Windows; //place it at the top of your view model class.
private Visibility _isVisible = Visibility.Collapsed;
public Visibility IsVisible
{
get
{ return _isVisible; }
set
{
if (_isVisible == value) { return; }
RaisePropertyChanging(() => IsVisible);
_passwordMissing = value;
RaisePropertyChanged(() => IsVisible);
}
}