DateTime need convert to string wpf - c#

<DataGrid....
<DataGrid.Resources>
<DataTemplate DataType="{x:Type DateTime}">
<TextBlock Text="{Binding StringFormat={}{0:d}}" />
</DataTemplate>
</DataGrid.Resources>
...
<DataGridTemplateColumn Header="Время оплаты">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Center" Text="{Binding date_payment}" Width="Auto" Height="Auto" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
but this column have type DateTime...
i need convert this column on this type(string), because i need rename value row on this column, i use event LoadingRow so
DataRowView item = e.Row.Item as DataRowView;
DataRow row = item.Row;
var time = row[4];
if (Convert.ToString(time) == "01.01.0001 0:00:00")
{
row[4] = "No payment";
}
but its wrong, row no converting to string, please help

First of all, you have both a cell template and a data template. Pick one. Second, since you have a data template anyway there's no reason to create a converter, much less a code-behind event handler. You can keep all the relevant code and text strings (what if you need to localize?) nicely in one place with a trigger:
<DataTemplate TargetType="{x:Type DateTime}">
<TextBlock x:Name="text" Text="{Binding StringFormat={}{0:d}}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Static DateTime.MinValue}">
<Setter TargetName="text" Property="Text" Value="No payment"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

In case if it's Nullable value you could use
Binding="{Binding date_payment, TargetNullValue={}Дата отсутствует}"
In case if not, use IValueConverter where you will check for MinDate.
Here is an Example how to use converters, and converter for you
public class DateConverter:IValueConverter
{
private const string NoDate = "Дата отсутствует";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is DateTime)
{
var date = (DateTime) value;
if(date==DateTime.MinValue)
return NoDate;
return date.ToString();
}
return NoDate;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

You shoud use Converter for this:
public class MyConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
if (value == DateTime.MinValue) {
return "No payment";
}
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
Than just add the converter to your binding.

Related

binding images in listbox

I have a listbox that is populated from a datatable. I want each item to have a specific image on listbox, but I want to set the image depending of an id that each item has.
for example , I have :
Products
Orange
Apple
ID
1
2
and the images are named: Item.1.png , Item.2.png
So, in my listbox,where I have apple, I will have next to it the image named: Item.2.png.
My problem is that I don't know how could I do a conditional binding . I don't want to have on my template hundreds of lines that are doing this for each item. I need to do this using a condition, like : if(product.id==1), Image.Source=Item.1.png.
Is there any way to do this in wpf?
It sounds to me like you need an IdToImageConverter that will decides which Image should be shown dependant on the value of the Id property. Something like this should do the trick:
[ValueConversion(typeof(int), typeof(ImageSource))]
public class IdToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType() != typeof(int) || targetType != typeof(ImageSource)) return false;
int id = (int)value;
if (id < 0) return DependencyProperty.UnsetValue;
string imageName = string.Empty;
switch (id)
{
case 1: imageName = "Item.1.png"; break;
case 2: imageName = "Item.2.png"; break;
}
if (imageName.IsEmpty()) return null;
return string.Format("/AppName;component/ImageFolderName/{0}", imageName);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
You could then use it in your ListBox.ItemTemplate something like this:
<YourConvertersXmlNamespacePrefix:IdToImageConverter x:Key="IdToImageConverter" />
...
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Id, Converter={StaticResource
IdToImageConverter}}" />
<TextBlock Text="{Binding Name}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As I understand your question, every object in the listbox has an ID property, where you want the image to be item.ID.png.
You could use a converter in your binding to do this. So in your listbox template, you can have something like:
// ... Listbox template
<Image Source={Binding pathToItemID, Converter={StaticResource MyConverter}/>
// ... Remaining ListBox template
You will need to add the converter to the UserControl's resources:
<UserControl.Resources>
<xmlnsPointingToConverter:MyConverter x:Key="MyConverter"/>
</UserControl.Resources>
Then add a MyConverter class which implements IValueConverter:
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return string.Format("item.{0}.png", value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Change Binding value in XAML

I need to make some complex binding in XAML. I have a DependencyProperty typeof(double); let's name it SomeProperty. Somewhere in XAML code of my control, I need to use the whole SomeProperty value, somewhere only a half, somewhere SomeProperty/3, and so on.
How can I do something like:
<SomeControl Value="{Binding ElementName=MyControl, Path=SomeProperty} / 3"/>
:)
Looking forward.
Use a division ValueConverter:
public class DivisionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int divideBy = int.Parse(parameter as string);
double input = (double)value;
return input / divideBy;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
<!-- Created as resource -->
<local:DivisionConverter x:Key="DivisionConverter"/>
<!-- Usage Example -->
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=1}"/>
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=2}"/>
<TextBlock Text="{Binding SomeProperty, Converter={StaticResource DivisionConverter}, ConverterParameter=3}"/>

WPF Trigger that would work if the value is equal or greater

I wrote an application in WPF that has a button and slider. I would like to create a trigger for the button, which would set the button's 'IsEnable' property to false when the slider value is greater than another value.
Right now I have:
<Style x:Key="zoomOutButton" TargetType="Button" BasedOn="{StaticResource ResourceKey=buttonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentAltitude}" Value="24000">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
But I would like to set isEnable not when the value of CurrentAltitude equal 24000, but when it is equal or greater than 24000.
Any ideas?
You can achieve this using a converter:
public class IsEqualOrGreaterThanConverter : IValueConverter {
public static readonly IValueConverter Instance = new IsEqualOrGreaterThanConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
int intValue = (int) value;
int compareToValue = (int) parameter;
return intValue >= compareToValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
Then your trigger will look like this:
<Style x:Key="zoomOutButton" TargetType="Button" BasedOn="{StaticResource ResourceKey=buttonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentAltitude, Converter={x:Static my:IsEqualOrGreaterThanConverter.Instance}, ConverterParameter=24000}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
A more generic converter, usable with any comparable type, could be :
public class IsGreaterOrEqualThanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
IComparable v = value as IComparable;
IComparable p = parameter as IComparable;
if (v == null || p == null)
throw new FormatException("to use this converter, value and parameter shall inherit from IComparable");
return (v.CompareTo(p) >= 0);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
But in this case, the ConverterParameter must be interpreted with the same type as the value transmitted to your Converter. For example, to compare an int property 'MyIntProperty' with the contant int value 1, in your XAML, you can use this syntax :
<UserControl x:Class="MyNamespace.MyControl"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:genconverters="clr-namespace:MyConverterNamespace;assembly=MyConvertersAssembly">
<Grid>
<Grid.Resources>
<genconverters:IsGreaterOrEqualThanConverter x:Key="IsEqualOrGreaterThanConverter"/>
<sys:Int32 x:Key="Int1">1</sys:Int32>
</Grid.Resources>
<ComboBox IsEnabled="{Binding MyIntProperty,
Converter={StaticResource IsEqualOrGreaterThanConverter},
ConverterParameter={StaticResource Int1}}"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}"/>
</Grid>

Change true/false to a image

i have a column in a datagrid that the content is True/false, how can i change this true/false(boolean) to a image, according to the text?
I'm using c# wpf.
Edit:
<dg:DataGridTemplateColumn MinWidth="70" Header=" Is Done2">
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Name="imgIsDone" Source="../Resources/Activo.png"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsDone}" Value="False">
<Setter TargetName="imgIsDone" Property="Source" Value="../Resources/Inactivo.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>
public class BoolToImage : IValueConverter
{
public Image TrueImage { get; set; }
public Image FalseImage { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is bool))
{
return null;
}
bool b = (bool)value;
if (b)
{
return this.TrueImage;
}
else
{
return this.FalseImage;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then in your xaml, as a resource:
<local:BoolToImage TrueImage="{StaticResource Image}" FalseImage="{StaticResource FalseImage}" x:Key="BoolImageConverter"/>
Then in your binding:
ImageSource={Binding Path=BoolProp,Converter={StaticResource BoolImageConverter}}"
Use a DataGridTemplateColumn to supply a DataTemplate for the column that contains an Image, and use a value converter or a data trigger to set the image source based on the value of the column. Here is an example that uses a data trigger:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Name="MyImage" Source="TrueImage.png"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding BoolColumn}" Value="False">
<Setter TargetName="MyImage" Property="Source" Value="FalseImage.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
In case someone struggles getting the answer(from benPearce) running, i had to modify the converter to use ImageSource!
using System;
using System.Windows.Data;
using System.Windows.Media;
namespace ViewManager
{
public class BoolToImageConverter : IValueConverter
{
public ImageSource TrueImage { get; set; }
public ImageSource FalseImage { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is bool))
{
return null;
}
bool b = (bool)value;
if (b)
{
return this.TrueImage;
}
else
{
return this.FalseImage;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
usage with a resource
<local:BoolToImageConverter x:Key="BoolToImageConverter" FalseImage="{StaticResource UnLockedSource}" TrueImage="{StaticResource LockedSource}" />
...
<Button Grid.Column="2" Command="{Binding LockUnlockCommand}" >
<Image Source="{Binding IsLocked, Converter={StaticResource BoolToImageConverter}}" MinHeight="50" MinWidth="50" />
</Button>

Assign enum property in xaml using silverlight

I have a property of datattype enum : like
public BreakLevel Level
{
get { return level; }
set { level = value; }
}
And enum defined :
public enum BreakLevel
{
Warning, Fatal
}
I want bind the neum property to the visibility of my border , somewhat like this:
Visibility="{Binding BreakLevel.Fatal}"
so is it possible?
<Border CornerRadius="4" BorderThickness="1" BorderBrush="#DAE0E5"
Visibility="{Binding DataContext.IsError, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}" >
Scott has a good answer to the actual question, however its always a good idea to ask yourself "How might I need code like this in the future? How can I avoid creating yet another class and instead re-use what I have already got?".
Here is a more general variation of Scott's solution:-
public class EnumToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (Enum.GetName(value.GetType(), value).Equals(parameter))
return Visibility.Visible;
else
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
Xaml:-
<TopLevelWindowOrControl.Resources>
<local:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />
</TopLevelWindowOrControl.Resources>
<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter=Fatal" />
In this approach we can converter any enum to a Visibility value by using the ConverterParameter to specify the enum value (in string form) that constitute the "Visible" state.
Its tempting to take this further to allow more than one enum value to be equated to "Visible". However currently the code isn't much more complicated than Scott's more specific implementation. Hence this enhancement should be left until needed.
I think you can just create a BreakLevelToVisibilityConverter and bind just like the example you provided.
I'm assuming that the DataContext of your border is set to an instance of a class that has a property of type 'BreakLevel' (we'll call this property 'BreakLvlProperty').
The code below will then show the border if the value of BreakLvlProperty is BreakLevel.Fatal
Converter:
public class BreakLevelToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((BreakLevel)value == BreakLevel.Fatal)
return Visibility.Visible;
else
return Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
XAML:
<TopLevelWindowOrControl.Resources>
<local:BreakLevelToVisibilityConverter x:Key="BreakLevelToVisibilityConverter" />
</TopLevelWindowOrControl.Resources>
<Border Visibility="{Binding Path=BreakLvlProperty, Converter={StaticResource BreakLevelToVisibilityConverter}" />
public class EnumToVisibilityConvertor : IValueConverter
{
private bool chk;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((value != null) && (value is BreakLevel) && (targetType == typeof(Visibility)))
{
chk = ((((BreakLevel) value) == (BreakLevel) Enum.Parse(typeof (BreakLevel), parameter.ToString(), true)));
return (chk==true) ? Visibility.Visible : Visibility.Collapsed;
}
throw new InvalidOperationException("Invalid converter usage.");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
<Border CornerRadius="4" BorderThickness="1" BorderBrush="#DAE0E5"
Visibility="{Binding Path=Level, Converter={StaticResource enumToVisibilityConvertor},ConverterParameter=Fatal}" >
I know it's a bit old question but all of you focused on converters and there's much better (in my opinion) way of doing it without involving code-behind:
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<Grid>
<!-- Here is the border which will be shown if Object.Level has value Fatal -->
<Border x:Name="PART_Border"
Visibility="Collapsed"
BorderThickness="3" BorderBrush="Red"
CornerRadius="4">
</Border>
<TextBlock>Interiors of the border</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<!-- This is the code which turns on border's visibility -->
<DataTrigger Binding="{Binding Level}" Value="{x:Static local:BreakLevel.Fatal}">
<Setter TargetName="PART_Border" Property="Visibility" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
I assumed that in DataContext resists an object which has a property Level which is of your BreakLevel type.

Categories