I have two elements: a listbox and a "this list is empty" message. I'd like to bind their visibility to the list box's ItemsSource being empty. However, I'm not sure how to do this:
<TextBlock Text="No favorite searches yet. Add some by searching, then clicking 'Add to Favorites'"
Padding="10,0"
VerticalAlignment="Center"
Visibility="{Binding Path=FavoriteFilters.IsEmpty, Converter={StaticResource visibilityConverter}}"
/>
<ListBox ItemsSource="FavoriteFilters"
x:Name="favoriteFiltersList"
Visibility="{Binding Path=FavoriteFilters.IsEmpty, Converter={StaticResource visibilityConverter}}">
<ListBox.ItemTemplate>
<DataTemplate>
<my:FavoriteFilterLink />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
They are both visible, although the ItemsSource is empty. Also, I'm not sure how to invert the condition for the ListBox.
The visibility converter:
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool?)
{
if (string.IsNullOrEmpty((string)parameter))
{
return (value as bool?).Value ? Visibility.Visible : Visibility.Collapsed;
} else
{
return (value as bool?).Value ? Visibility.Collapsed : Visibility.Visible;
}
}
throw new ArgumentException();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
You might be better off writing two converters, one for the ListBox the other for the TextBlock. The logic of each would be simpler and you wouldn't need to pass a parameter to get the correct result.
While it might not be as elegant as a single converter solution it will be far more maintainable.
If you really want to pass a parameter then you need to use the ConverterParameter.
There's an example here but I'm not 100% sure it'll meet your requirements. The simplified XAML syntax is:
<TextBlock Visibility="{Binding FavoriteFilters.IsEmpty,
Converter={StaticResource visibilityConverter}, ConverterParameter=false}"/>
<ListBox Visibility="{Binding FavoriteFilters.IsEmpty,
Converter={StaticResource visibilityConverter}, ConverterParameter=true}"/>
Then in your converter (simplified):
bool show = (bool)value;
bool visible = (bool)parameter;
if (visible)
{
return show ? Visibility.Visible : Visibility.Collapsed;
}
else
{
return show ? Visibility.Collapsed : Visibility.Visible;
}
Related
I've a combobox, which allows me to select a type. When I select a type, i'm able to fill a component. But I'd like that my component corresponding to my type. So, if it's a date, i'd like to display a datepicker, and if it's a string, i'd like to display a textbox.
How can I do that ?
I don't want to change things around DataTemplate, because this row is a part of a datagrid :)
<DataGridTemplateColumn Header="SQLValue" Width="0.55*" CanUserResize="False" CanUserReorder="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- HERE ! HOW CAN I CHOOSE ONE BY A CONDITION ? -->
<DatePicker/>
<TextBox Text="{Binding SqlValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The idea here is: you should a property in data context call DispType (int)
Then in each control you binding Visibility with above property, include a Converter convert number to Visible or not, Converter have parameter is number.
You can see my eg:
<Grid>
<Button Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=1}"/>
<TextBox Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=2}"/>
<DatePickerTextBox Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=3}"/>
</Grid>
You see the hard code for ConverterParameter.
And Converter class
public class VisibilityTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int actualType = parameter == null ? 0 : System.Convert.ToInt32(parameter);
int compareType = value == null ? 0 : System.Convert.ToInt32(value);
if (actualType == compareType)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Please not that code is only demo, you should change code to meet your expectation.
I have a ListView with all kind of tasks that have to be completed. When a task is completed a user presses on the item in the listview. This changes a boolean in my web api. Now I want to display a check symbol on the items that are already completed when I get all the items from my API.
<SymbolIcon Grid.Column="0" x:Name="CompleteTask" Symbol="Accept"/>
<TextBlock Name="TaakNaam"
Grid.Column="1"
Text="{x:Bind TaskName}"
FontSize="16"/>
What it should be
you can write property
public Visibility TickVisibility
{
get {return YourBoolean == true ? Visibility.Visible : Visibility.Collapsed;}
}
and Bind it:
<SymbolIcon Grid.Column="0" x:Name="CompleteTask" Symbol="Accept" Visibility={Binding TickVisibility}/>
or use NotifyProperty every time YourBoolean has changed
or write Converter that will implement IValueConverter and will convert bool<=>Visibility
I created this Converter:
public class BooleanToVisibilityConverter : IValueConverter
{
public BooleanToVisibilityConverter()
{
}
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is bool && (bool) value)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return (value is Visibility && (Visibility)value == Visibility.Visible);
}
}
And imported this in my view:
<Page.Resources>
<vm:BooleanToVisibilityConverter x:Key="BoolToVis" />
</Page.Resources>
Than I added a binding to my SymbolIcon:
<SymbolIcon Grid.Column="0" x:Name="CompleteTask" Symbol="Accept" Foreground="Green" Visibility="{Binding Path=Check, Converter=StaticResource BoolToVis}}"/>
Source: https://pmdevweb.wordpress.com/2016/05/24/uwp-binding-boolean-to-visibility/
In a Windows Phone 8 app,
I have a listbox with 2 TextBlocks and a button.
I have a list of 2 strings and a boolean & I am able to bind the strings to the TextBlocks.
<ListBox Name="ListboxTest">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Value}" TextWrapping="Wrap"/>
<Button />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And this is the C# code to bind to the list box.
public class Detail
{
public string Key { get; set; }
public string Value { get; set; }
public bool check { get; set; }
}
public List<Detail> ClassList = new List<Detail>();
ListboxTest.ItemsSource = ClassList;
I want to display the button only when the boolean value is true.
How do I do it?
Take a look at this. Actually what you really need is a Converter by implementing the IValueConverter. This is also a good example where you could read about it. Bind the boolean value with the visibility property of the button and you are done! ;)
You can use boolean to visibility converter to hide, show button
Here are example:
public class BoolToVisibility : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var boolValue = false;
if (value != null) boolValue = (bool)value;
return boolValue ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
In app.xaml
<my:BoolToVisibility x:Key="BoolToVisibility"/>
In your data template
<Button Visibility="{Binding Path=YourBoolProperty,Converter={StaticResource BoolToVisibility}}>
Or, you could add this property to the Detail class:
public Visibility ButtonVisibility {
get {
return this.check == true ? Visibility.Visible : Visibility.Collapsed;
}
}
And then just bind the button's Visibility to the ButtonVisibility property without any converters.
<Button Visibility="{Binding ButtonVisibility}" />
Please try those use Triggers.
Various Triggers in windows phone Msdn.
Please use ObservableCollection in WP8 for binding instead of List.
Please make your properties are implemented with INotifyPropertyChanged If your Boolean property is not implemented with inotifypropertychanged the view will not know the value is changed.hence the Data trigger will not work.
Namespace
xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
x:Class="XXX_XXXX"
<Button Content="My button"
Stretch="None"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<interactivity:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding Check}" Value="True">
<ec:ChangePropertyAction PropertyName="Visibility">
<ec:ChangePropertyAction.Value>
<Visibility>Visible</Visibility>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>
<ec:DataTrigger Binding="{Binding Check}" Value="False">
<ec:ChangePropertyAction PropertyName="Visibility">
<ec:ChangePropertyAction.Value>
<Visibility>Collapsed</Visibility>
</ec:ChangePropertyAction.Value>
</ec:ChangePropertyAction>
</ec:DataTrigger>
</interactivity:Interaction.Triggers>
</Button>
Note Answered from phone syntax may not be correct
I have a collection databound to a ListBox. What I would like to do is show some UI based on whether or not some property of the member of the collection exists.
E.g.:
public class Widget
{
public string foo;
public string bar;
}
public ObservableCollection<Widget> Stuff;
XAML:
<ListBox ItemsSource="{Binding Stuff}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding foo}"
Visiblity="{Binding
(foo != null ? Visibility.Visible : Visibility.Collapsed)
}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note the Visibility attribute on the TextBlock. Clearly this isn't supported, but it should give you an idea of what I want to do.
One possible solution is that I could add a property to widget that looks like this:
public Visibility has_foo;
And then:
... Visibility="{Binding has_foo}" ...
But it seems awkward to have to generate these additional properties.
I suspect there is a much better way. Is there? How would you do it?
Thanks.
Create a value converter. Something like
public class NullToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then add it something like
<YourUserControl.Resources>
<NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
</YourUserControl.Resources>
<ListBox ItemsSource="{Binding Stuff}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding foo}"
Visiblity="{Binding foo,
Converter={StaticResource NullToVisibilityConverter}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Obviously I've not implemented ConvertBack (not really sure if you will be able to convert back) but you shouldn't need it in this instance.
Is it possible to display this TextBlock, only if the Address.Length > 0 ? I'd like to do this directly into the xaml, I know I could put all my controls programmatically
<TextBlock Text="{Binding Path=Address}" />
Basically, you're going to need to write an IValueConverter so that you can bind the Visibility property of your TextBox to either the Address field, or a new field that you create.
If you bind to the Address field, here's how the binding might look like::
<TextBlock Text="{Binding Path=Address}"
Visibility="{Binding Path=Address, Converter={StaticResource StringLengthVisibilityConverter}}" />
And then StringLengthVisiblityConverter could look something like this:
public class StringLengthVisiblityConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || value.ToString().Length == 0)
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Don't need to implement this
}
}
Then you'd just need to add your converter as a resource, using syntax like this (where src is mapped to the namespace where the converter is defined):
<src:StringLengthVisiblityConverter x:Key="StringLengthVisiblityConverter" />
I would do this with another boolean property called HasAddress which returns Address.Length > 0.
<!-- In some resources section -->
<BooleanToVisibilityConverter x:Key="Bool2VisibilityConverter" />
<TextBlock
Text="{Binding Address}"
Visibility="{Binding HasAddress, Converter={StaticResource Bool2VisibilityConverter}}"
/>
You should also remember to notify the property change for HasAddress in the setter of Address.
You can create a StringToVisibility converter.
It will return Visibility.Visible if bound string is not null or empty and Visibility.Collapsed if it is.
Use this converter while binding Address with Visibility property of your TextBlock.
Example:
<TextBlock Text="{Binding Path=Address}" Visibility="{Binding Address, Converter={StaticResource StringToVisibilityConverter}}" />