I am running into a strange situation where the image won't show up if its visibility is first set to collapsed and latter set to visible through binding.
<ListView Grid.Row="0" ItemsSource="{Binding SystemCheckEntries}">
<GridViewColumn DisplayMemberBinding="{Binding State}" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="info.png"
Height="14"
ToolTip="{Binding Message}"
Visibility="{Binding Message, Converter={StaticResource StringNullOrEmptyToVisibilityConverter}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Converter:
public class StringNullOrEmptyToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.IsNullOrEmpty((string) value) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
if I use Visibility.Collapsed in converter then the result looks like
and if I open up visual tree to check the property of the image
which says its suppose to be "Visible" (but apparently not)
If I use Visibility.Hidden in converter then the result looks like
Which is exactly what I wanted. But then I don't want the icon to take up extra space when its not showing.
So .. why is this happening?
Some conjecture: The first items have no width (because they are collapsed), the ListView sets the column width to 0. New items are added that have an image but it's not shown because the column has no width.
Edit: Just confirmed this behaviour.
Related
As of now, i assign the image of a TreeView item using a direct binding to the image's source:
<DataTemplate DataType="{x:Type local:GeoPoint}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Color}" Height="32" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
the Color binding is referring to string containing the path to the PNG, something like "/Resources/red.png"
i would like to make the Color variable of custom type "MarkerColor", an enum containing several colors, and have the image source binding reference this value, so that if
Color = MarkerColor.green; the binding would reference "/Resources/green.png"
Note that the name of the PNG is not necessarily the same as the name of MarkerColor, an "adapter" should be used to convert the type
I know how to do this in Java Android SDK, but not really sure on how to achive this in Wpf
You could create a converter that knows how to convert the enumeration value to a valid resource:
public class ColorResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
MarkerColor color = (MarkerColor)value;
Uri uri;
switch(color)
{
case MarkerColor.Green:
uri = new Uri("Resources/green.png");
break;
case MarkerColor.Red:
uri = new Uri("Resources/red.png");
break;
//...
default:
uri = new Uri("Resources/default.png");
break;
}
return new BitmapImage(uri);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Usage:
<DataTemplate DataType="{x:Type local:GeoPoint}">
<DataTemplate.Resources>
<local:ColorResourceConverter x:Key="ColorResourceConverter" />
</DataTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Color, Converter={StaticResource ColorResourceConverter}}" Height="32" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
I'm developing a small application that needs to check some availability properties. I'm using for the user interface WPF. I need to change some foreground colors if a selection from a combobox. I have this DataTemplate:
<DataTemplate x:Key="userTemplate">
<TextBlock VerticalAlignment="Center">
<Image Source="imgsource.png" Height="25" Width="25" />
<Run Text="{Binding BooleanObjectName}" Foreground="{Binding boolobject, Converter={StaticResource convAvailability}}"/>
</TextBlock>
So I'm using for this convertion a IValueConverter that sets the color to the foreground:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BooleanObject boolobject = (BooleanObject)value;
if (boolobject.IsBoolValueOne) return System.Drawing.Brushes.Green;
else if (boolobject.IsBoolValueTwo) return System.Drawing.Brushes.Red;
else if (boolobject.IsBoolValueThree) return (SolidColorBrush)(new BrushConverter().ConvertFrom("#d3d300"));
else return System.Drawing.Brushes.Black;
}
What is wrong with this, because in my interface I'm always getting the black color. Any thoughts on this ?
Any help would be very much appreciated.
Thanks in advance.
As pointed out by #Funk you return the wrong kind of brushes. You should return a System.Windows.Media.Brush object:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BooleanObject boolobject = (BooleanObject)value;
if (boolobject.IsBoolValueOne)
return System.Windows.Media.Brushes.Green;
else if (boolobject.IsBoolValueTwo)
return System.Windows.Media.Brushes.Red;
else if (boolobject.IsBoolValueThree)
return (SolidColorBrush)(new BrushConverter().ConvertFrom("#d3d300"));
return System.Windows.Media.Brushes.Black;
}
Then it should work provided that your binding to the boolobject property actually works. Otherwise your converter won't get invoked at all.
If you want to bind to the object itself, you should specify a path of '.':
<TextBlock VerticalAlignment="Center">
<Image Source="imgsource.png" Height="25" Width="25" />
<Run Text="{Binding BooleanObjectName}" Foreground="{Binding Path=., Converter={StaticResource convAvailability}}"/>
</TextBlock>
I have a combobox which data source comes from a table in my DataBase. So, each item in my combo is an Object from the table. This Object have an attribute which corresponds to a string full of "1"s or "0"s. On the other hand I have a list of checkboxes inside of a ListBox with this template:
<ListBox Height="150" MinHeight="100" HorizontalAlignment="Center" Name="lstEstudios" VerticalAlignment="Top" Width="200"
ItemsSource="{Binding}" SelectionMode="Multiple" Margin="0,20,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="chkEstudios" Width="Auto" Content="{Binding Path=Nom_estudio}"
Checked="chkEstudios_Checked" Unchecked="chkEstudios_Unchecked"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I donĀ“t know if it's possible but, that I want to do is, for each "1" or "0" in the attribute set the checkbox checked or unchecked depending if there is a "1" check the checkbox or if is "0" uncheck the checkbox, and so on... with all the checkboxes in the ListBox, how to do that ?
I tried the same thing with my own sample having a CustomTask class.
<ListBox ItemsSource="{Binding CustomTasks}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding TaskStatus, Converter={x:Static testApp:StatusToBooleanConverter.Instance}}" Content="{Binding TaskStatus}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
where the TaskStatus is a boolean of two values, i.e Completed and Pending.
and here is the code for the converter
public class StatusToBooleanConverter : IValueConverter
{
public static StatusToBooleanConverter Instance = new StatusToBooleanConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Status)
{
switch ((Status)value)
{
case Status.Completed:
return true;
case Status.Pending:
return false;
}
return null;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Just try this out. Hope that helps.
This is a good place to use a converter. If you have a property with 1's and 0's in it and you want to translate those to true/false for the checked attribute then try making converters to do the work. The basic idea behind a converter is to take an input value (from a bound property) and, as the name implies, convert it to a different value. You can make them as simple or complicated as you would like, and turning "1" into true and "0" into false should be pretty quick.
You will bind the IsChecked attribute of the checkbox to your source of 1's and 0's and in the binding also use the converter.
If you haven't made a value converter before here is a nice tutorial on making one: http://wpftutorial.net/ValueConverters.html
I have a ListBox, which uses data binding for content (bound to an ObservableCollection), and an ItemTemplate for layout. Within the ItemTemplate, there is a TextBlock displaying a date (from the ObservableCollection), and a colored Rectangle.
I want the rectangle's fill color to change based on the date (to indicate age). However, since the Rectangle itself isn't bound to the date (and I don't see how it could be), I haven't been able to get a DataTrigger to work to alter the fill color.
Is there another way to get the Rectangle color to be controlled by the data binding?
Edit:
Here is a (simplified) copy of my ListBox ItemTemplate, as requested. Right now, the Rectangle's fill is a set color, but I want to change it to vary based on the targetstartdate field.
<ListBox Name="listBox1" ItemsSource="{Binding Path=testList}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="#FF009A00" Width="5" StrokeThickness="1" Margin="0,1,4,1"/>
<TextBlock Text="{Binding targetstartdate}" Margin="0,0,0,4" Foreground="#FF009A00" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can bind the rectangle's Fill or Stroke property to the Date. Then, use an IValueConverter to convert the date to the appropriate color.
<Window.Resources>
<local:DateToBrushConverter x:Key="DateToBrushConverter" />
</Window.Resources>
<Rectangle Fill="{Binding targetstartdate,Converter={StaticResource DateToBrushConverter}}"
... />
The Convert method should return a Brush object, which matches the Rectangle.Fill property.
public class DateToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var date = value as DateTime?;
if (!date.HasValue)
return new SolidColorBrush(Colors.Transparent);
else if (!date.Value > DateTime.Today.AddDays(-1))
return new SolidColorBrush(Colors.Blue);
// etc
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Bind rectangle's color to an IValueConverter, use the date as binding and determine the color based on the date inside the IValueConverter class.
I have a Data Grid. Its Item source is set to a List. My problem is that Iam unable to apply string formatting . This is formats Ive tried . Am I missing some thing ?
StringFormat='MM/dd/yyyy'
StringFormat={0:dd-MMM-yyyy}
Attached the resultant grid
<sdk:DataGridTemplateColumn Header="Recieved Date" Width="Auto" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=RecievedDate, StringFormat=\{0:dd-MMM-yyyy\} }" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<sdk:DatePicker Name="dtpFinancialAndComplianceLog" Text="{Binding Path=RecievedDate,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
If I understand what you're trying to do correctly, you have a DataGrid column which you want to display a DateTime object in a certain format. Ordinarily a DateTime object will sort out its own formatting depending on the System.Threading.Thread.CurrentUICulture.
Easiest way I know of to force any object into a certain format is to use a custom IValueConverter:
namespace MyProject.Converters
{
public class FormatConverter : IValueConverter
{//Suitable only for read-only data
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return string.Empty;
if(string.IsNullOrEmpty(parameter.ToString()))
return value.ToString();
return string.Format(culture, parameter.ToString(), value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
After adding a namespace to your xaml: xmlns:conv="clr-namespace:MyProject.Converters" and declaring your converter in the control's resources <conv:FormatConverter x:Key="Formatter" />, you will need to bind your column's data using your new converter:
<TextBlock Text="{Binding Path=RecievedDate, Converter={StaticResource Formatter}, ConverterParameter=\{0:dd-MMM-yyy\} }" />