How do I convert string values to integers and back using IValueConverter?
I have a database that consists of two tables; table CompanyX and table DeptY.
Table CompanyX has field ID(int), firstName, lastName, Email, Phone.
Table DeptY has field pID(int), Roles.
DeptY pID is foreign key To CompanyX ID. Every time I select someone in the Combobox, I want it to display as their ID in a DataGrid.
This is my ItemTemplate below:
<Application.Resources>
<DataTemplate x:Key="myTemplate">
<WrapPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding FirstName}"/>
<Label />
<TextBlock Text="{Binding LastName}"/>
</WrapPanel>
</DataTemplate>
</Application.Resources>
This is my Combobox which is bound to the ItemTemplate:
<ComboBox Height="23" HorizontalAlignment="Right" Margin="0,90,267,0"
Name="comboID" ItemsSource="{Binding}" VerticalAlignment="Top"
Width="208" ItemTemplate="{StaticResource myTemplate}" />
And a DataGrid which displays:
<DataGridTemplateColumn x:Name="pIDColumn" Header="Person ID" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=pID, Converter= {StaticResource myConverter}}"/>
<DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn x:Name="rolesColumn" Header="Roles" Width="auto" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Roles}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
IValueConverter which is not converting!!
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string a = (string)value;
int b;
int.TryParse(a, out b);
return b;
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
You are converting the wrong way around. Convert() takes the binding source as input (int in your case), and outputs what the xaml is expecting (string).
But you don't even need a converter. You can bind straight to an int and WPF will automatically call ToString() on it to display it as text.
Like was said in the other answer, you are doing it backwards. The Convert side of an IValueConverter is meant for converting from the source property to what is in the bound element, in your case a textbox. You need to do your parsing on the ConvertBack side because that is what takes what is in the textbox (a string) and converts it back to a number.
public class IntToString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
int ret = 0;
return int.TryParse((string)value, out ret) ? ret : 0;
}
}
Related
I have a nested datagrid and I want to hide outer datagrid column when the inner datagrid doesn't have any data. I am using MVVM pattern. Model fills the data in the collections which is binded to the view.
Filled Datagrid
The list of Component1, 2 and 3 are displayed through a datagrid inside the outer datagrid. Each label family will have two collections left and right.
When the Model doesn't have any components for left label collection, then I want the Left column to be hidden completely. As in below image. Similarly for Right column.
Left Column Hidden
Please help me in achieving this.
I searched for similar situations on this site and google, but couldn't find anything similar to this.
Here is the XAML code:
<DataGrid ItemsSource="{Binding Labels}"
CanUserAddRows="False"
CanUserDeleteRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Width="10*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LabelFamily}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Right" Width="25*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding LeftLabel.Components}"
CanUserAddRows="False"
CanUserDeleteRows="False">
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Left" Width="25*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding RightLabel.Components}"
CanUserAddRows="False"
CanUserDeleteRows="False">
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I am not posting the model code to keep the post short as much as possible.
You can create converter like this (I used ObservableCollection for testing, you should use your container):
public class NoElementVisibilityConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
ObservableCollection<int> ienum = value as ObservableCollection<int>;
return ienum == null || ienum.Count() == 0 ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
_converter = new NoElementVisibilityConverter();
return _converter;
}
private static NoElementVisibilityConverter _converter = null;
}
And use it on your column like this:
<DataGridTemplateColumn Header="Left" Width="25*"
Visibility={Binding RightLabel.Components, Converter={local:NoElementVisibilityConverter}>
Don't forget to include Converter namespace in your Window.
I have a DataGridTextColumn containing a boolean, these booleans return TRUE or FALSE on the Column.
I want to replace this by two images, one for TRUE, one for FALSE.
this is the DataGrid:
<DataGrid x:Name="DonneesBrutes" IsReadOnly="True" ItemsSource="{Binding Path=ResultatCollectionGrande}" Margin="10,65,0,0" AutoGenerateColumns="False" EnableRowVirtualization="True" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTextColumn x:Name="PrisEnCompte" Width="50" Binding="{Binding Path=Flag, Converter={StaticResource BooleanConverter}}" Header="PEC"></DataGridTextColumn>
with the resource:
<Window.Resources>
<local:BooleanConverter x:Key="BooleanConverter"/>
</Window.Resources>
this is the converter:
public class BooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value.Equals(true)) return #"booleanTrue.png";
return #"booleanFalse.png";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The converter works, it changes what my DataGridTextColumn displays. Now it Displays "booleanTrue.png" for TRUE and "booleanFalse.png" but it doesn't display the images.
How can I display'em, what am I missing to print these images in my DataGrid?
Thanks in advance for your help.
Instead of using a DataGridTextColumn you will require Template column to display Image within this Column and apply your binding in this template column only. let me show you the way
Your datagrid should be like this
<DataGrid x:Name="DonneesBrutes" IsReadOnly="True" ItemsSource="{Binding Path=ResultatCollectionGrande}" Margin="10,65,0,0" AutoGenerateColumns="False" EnableRowVirtualization="True" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTemplateColumn Header="PEC" x:Name="PrisEnCompte">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Height="50" Width="50" Source="{Binding Path=Flag, Converter={StaticResource booleanConverter}}"></Image>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
and your Boolean converter should be like this.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value.Equals(true))
return new Uri(#"C:\Users\pj827192\Desktop\Untitled.png");
return new Uri(#"C:\Users\Public\Pictures\Sample Pictures\Hydrangeas.jpg");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
Maybe you should return the markup for embedding the image instead of just the image name.
I have a data template with a TexBlock in XAML. This TexBlock shows a word in a word list. Every word I want to put the first letter capitalized, because all words are in lowercase.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="AddrBookItemTemplate">
<StackPanel VerticalAlignment="Top">
<TextBlock Margin="5,0,0,0" FontSize="20" Text="{Binding name}" />
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
In c# implement the converter
namespace Converter.ViewModels
{
public class ToCapitalizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return char.ToUpper(value.ToString()[0]) + value.ToString().Substring(1);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (value as string).ToLower();
}
}
}
In App.xaml
...
xmlns:vm="clr-namespace:Converter.ViewModels"
<Application.Resources>
<vm:ToCapitalizeConverter x:Key="ToCapitalizeConverter"/>
</Application>
In MainPage.xaml
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="AddrBookItemTemplate">
<StackPanel VerticalAlignment="Top">
<TextBlock Margin="5,0,0,0" FontSize="20" Text="{Binding name, Converter={StaticResource ToCapitalizeConverter}}" />
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
You can use a converter as follows:
<TextBlock Margin="5,0,0,0" FontSize="20" Text="{Binding name, Converter ={StaticResource myConverter}}" />
Specific information on how to implement a converter can be found here. You can essentially perform any operation you like on the text. I actually like Humanizer to do these type of text conversions.
I have a ObservableCollection<TimeSpan> Laps which I am databinding to a gridview. This works as expected but I need to apply a converter to set the format of the TimeSpan:
In my resources:
<utils:TimeToStringConverter x:Key="myConverter"/>
My Gridview:
<GridView HorizontalAlignment="Left" Height="278" Margin="78,220,0,0" VerticalAlignment="Top" Width="1278" ItemsSource="{Binding model.Laps}" />
I have the following converter which I want to apply on the items of a GridView / ListView in Winrt:
public class TimeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
TimeSpan t = (TimeSpan) value;
return t.ToString(#"hh\:dd\:ss\.fff");
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
I can't figure out how to get the converter to work, and when I apply it on the GridView then it is looking for me to convert an Observable collection rather than just a TimeSpan item. What should I do here ?
Regards
You need something like a
<GridView
...>
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Converter={StaticResource myConverter}}" />
</DataTemplate>
</GridView.ItemTemplate>
Use the below modified line
I've just modified the item source like below
ItemsSource="{Binding model.Laps,Converter={StaticResource myConverter}}"
<GridView HorizontalAlignment="Left" Height="278" Margin="78,220,0,0" VerticalAlignment="Top" Width="1278" ItemsSource="{Binding model.Laps,Converter={StaticResource myConverter}}" />
I'm trying to make cell bold or normal if item new/old inside DataGrid but stumbled upon erro..
Looks like my issue described here: Why can I not bind the Visiblity of a DataGridTemplateColumn in Silverlight 4?
I'm getting following error:
Object of type 'System.Windows.Data.Binding' cannot be converted to
type 'System.Windows.FontWeight'.
And my XAML looks like so:
<sdk:DataGridTextColumn Header="Subject" Binding="{Binding Subject}" CanUserReorder="True" CanUserResize="True" CanUserSort="True" Width="Auto" FontWeight="{Binding IsNew, Converter={StaticResource BoolToFontWeightConverter}}" />
My question is there any workaround to get this working? I'm not even using template column, it's plain text column..
public class BoolToFontWeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((bool)value) ? FontWeights.Bold : FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (FontWeight)value == FontWeights.Bold;
}
}
The FontWeight property of the DataGridTextColumn is not a dependency property and thus will not support bindings. A workaround would be to use a DataGridTemplateColumn with a TextBox as the DataTemplate and set the appropriate bindings there, something like:
<sdk:DataGridTemplateColumn Header="Subject"
CanUserReorder="True"
CanUserResize="True"
CanUserSort="True"
Width="Auto">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Subject}" FontWeight="{Binding IsNew, Converter={StaticResource BoolToFontWeightConverter}}"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>