WPF Combobox bind text - wpf

Maybe a simple task but I can't find the solution. I have a combobox connected to a database. Instead of displaying the content of ProductLookup I just want to display the words 'male' and 'female' on the popup menu.
Thank you
<ComboBox Height="23" Name="ComboBox2" Width="120" IsEditable="False"
ItemsSource="{Binding Source={StaticResource ProductLookup}}"
SelectedValue="{Binding Path=ProductID}"
SelectedValuePath="ProductID"
DisplayMemberPath="Name"/>

Write a Converter that takes one of your "Product" objects....looks at the gender related data inside it, or does the gender determining logic, and then returns the gender string, "male" or "female".
Then use it in your XAML to set the TextBlock:
<StackPanel Height="197" HorizontalAlignment="Left" Margin="300,6,0,0" Name="StackPanel5" VerticalAlignment="Top" Width="285"
DataContext="{Binding Source={StaticResource DetailViewPagos}}">
<StackPanel.Resources>
<local:ProductToGenderConverter x:Key="prodtogenderconv"/>
</StackPanel.Resources>
<ComboBox Height="23" Name="ComboBox2" Width="120" IsEditable="False"
ItemsSource="{Binding Source={StaticResource ProductLookup}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource prodtogenderconv}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
public class ProductToGenderConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
MyProduct prod = value as MyProduct;
if (prod is for a male) // Pseudocode for condition
return "male";
if (prod is for a female) // Pseudocode for condition
return "female";
return null or "";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
Alternatively you could provide a ViewModel which wraps your Product object, which has a specific property that indicates the "genderness" of the Product...then create a collection of those objects for setting in your ComboBox...then you can use DisplayMemberPath to point to that property.

Please see this answer, it is a way to wrap your values for nice binding and display in WPF.
The Item class could be modified to support object for the Code property.

Related

WPF MarkupExtension binding error

refers to implementing a multilanguage interface now I have a problem. I have a grid where its ItemSource it's a Dictionary<string, string>: I can't give the key value as parameter of the markup extension because I have the following exception
A 'Binding' cannot be set on the 'Value1' property of type 'TranslateMarkupExtension'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
This is the xaml where I use the markup extension:
<ItemsControl ItemsSource="{Binding MyDictionary}" Grid.Row="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Content="{TranslateMarkup Value1 = {Binding Path = Key}}" Grid.Column="0" />
<TextBox Tag="{Binding Key, Mode=OneWay}" Text="{Binding Value, Mode=OneWay}" Width="200" Height="46" VerticalContentAlignment="Center" Grid.Column="1" LostFocus="TextBox_OnLostFocus" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I can't find any workaround..I need the dictionary as item source because the label will show the key and the textbox the corresponding value..I tried also replacing the dictionary with a list of object but the problem still remains.
Does anyone have a good hint? Thanks in advance.
As suggested by Ed Plunkett, the solution is the ValueConverter.
So the label is know this:
<Label Content="{Binding Key, Converter={StaticResource MultiLangConverter}}" Grid.Column="0" />
where my ValueConverter is the following:
public class StringToMultiLangConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var stringValue = (string) value;
if (string.IsNullOrEmpty(stringValue))
return string.Empty;
string multiLang = LangTranslator.GetString(stringValue);
return multiLang ?? value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
Thanks for the help!

WPF binding TextBox and ObservableDictionary<Int64,String> (display String by Id)

Each item of my Employee's list has Post property. This property is Int64 type. Also, I have some ObservableDictionary<Int64,String> as static property. Each Employe must display the String value by its key.
DataTemplate for Employe item (I deleted the superfluous):
<DataTemplate x:Key="tmpEmploye">
<Border BorderThickness="3" BorderBrush="Gray" CornerRadius="5">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=Post}"/>
</StackPanel>
</Border>
</DataTemplate>
But this code displayed the Int64 value, not the String. String for getting static dictionary:
"{Binding Source={x:Static app:Program.Data}, Path=Posts}"
I know how solve it problem for ComboBox, but I don't know for TextBlock. For ComboBox I wrote it (it is works fine):
<ComboBox x:Name="cboPost" x:FieldModifier="public" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Margin="2" Grid.ColumnSpan="2"
ItemsSource="{Binding Source={x:Static app:Program.Data}, Path=Posts}" DisplayMemberPath="Value"
SelectedValuePath="Key"
SelectedValue="{Binding Path=Post, Mode=TwoWay}">
</ComboBox>
But how can I solve it for TextBlock?
mmmmm, I'm sure I have developed something for this scenario before but I can't remember or find anything related!
IMO you can use a converter, so you pass your Post (Int64) to the converter and it returns the string value from the dictionary, although it must be a better solution.
[ValueConversion(typeof(Int64), typeof(string))]
public class PostToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// validation code, etc
return (from p in YourStaticDictionary where p.Key == Convert.ToInt64(value) select p.Value).FirstOrDefault();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
}
}
XAML:
<Window ...
xmlns:l="clr-namespace:YourConverterNamespace"
...>
<Window.Resources>
<l:PostToStringConverter x:Key="converter" />
</Window.Resources>
<Grid>
<TextBlock Text="{Binding Post, Converter={StaticResource converter}}" />
</Grid>
</Window>

How to sort text from XML file as number in WPF DataGrid?

The content of my DataGrid (Product and Price, for example) is loaded from an XML file and every thing is treated as text when sorted by the DataGrid.
How to tell the DataGrid to treat Price as number when sorting? Thanks.
Here's the relevant XAML (there's NO code behind). I want to sort Length as number:
<DataGridTemplateColumn Header="Length" SortMemberPath="Length" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Right" VerticalAlignment="Center" Text="{Binding XPath=Length}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
You could add a Converter to your Binding.
Step 1 : Create the converter class.
[ValueConversion(typeof(string), typeof(int))]
public class StringToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Int32.Parse(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
}
A little validation might be advisable, but this is only a rudimentary example.
Step 2: instantiate the converter. Make sure you add the Namespace declaration to your Xaml.
<Window.Resources>
<StringToIntConverter x:Name="stringToInt"/>
</Window.Resources>
Step3 : use it
<DataGridTemplateColumn Header="Length" SortMemberPath="Length" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Right" VerticalAlignment="Center" Text="{Binding XPath=Length, Converter={StaticResource stringToInt}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Without code, this is just a guess, but I'm assuming you are doing a xml deserialization into an object, that is put in a list and then your datagrid is bound to the list. If you make the price data field in the list class an int, then datagrid will treat it as a number.

WPF pass parent binding object to the converter

I have ItemsControl that is bound to collection of type Student.
Inside the ItemTemplate I have a TextBox that uses IValueConverter to do some custom calculations and logic. I want to pass the actual Student object to the value converter, instead a property of it. How can I do that? Here's a sample of my code.
<ItemsControl ItemsSource="{Binding StudentList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding ????, Converter={StaticResource MyConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In the code I have this
public class MyValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// I want 'value' to be of type Student.
return null;
}
}
You can just leave out the path. That way you get at the actual object bound to.
<TextBlock Text="{Binding Converter={StaticResource MyConverter}}"/>
or if you want to be explicit about it:
<TextBlock Text="{Binding Path=., Converter={StaticResource MyConverter}}"/>

Data Binding in Combobox

I binded a database table's primary key to the selectedIndex of a combobox. the problem occurs where the primary key starts from 1 but selectedIndex accepts from 0. I mean, when I want to see the item with ID=1 in database, since it's listed as first element in combobox with index 0, it displays the second element in the list, which is considered with ID=1 in the combobox. Can anyone help me on solving this problem?
Thanks in advance.
here's my combobox:
<ComboBox SelectedIndex="{Binding SC.User1.UserID, UpdateSourceTrigger=PropertyChanged }"
IsSynchronizedWithCurrentItem="True"
x:Name="proxyResponsibleUserCmb" ItemsSource="{Binding Users, Mode=OneTime}"
SelectedItem="{Binding SC.User1.FullName, ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{x:Null}"
Height="23"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="118"
Margin="184,3,0,0"
Grid.Row="0"
Grid.Column="1"/>
What about using the ComboBox's SelectedValuePath and DisplayMemberPath, and setting your default item with SelectedValue instead of SelectedItem?
<ComboBox x:Name="proxyResponsibleUserCmb"
SelectedValuePath="{Binding UserID}"
DisplayMemberPath="{Binding FullName}"
SelectedValue="{Binding SC.User1.UserId, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Users, Mode=OneTime}" />
Does setting the property IsSynchronizedWithCurrentItem (in your XAML) to True help?
EDIT
Maybe this link will help:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/b4e84ea2-9597-4af1-8d3c-835b972e3d73
Quick workaround via a ValueConverter:
Create a ValueConverter in your codebehind:
// of course use your own namespace...
namespace MyNameSpace
{
public class IndexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if(!(value is int)) // Add the breakpoint here!!
throw new Exception();
int newindex = ((int)value - 1;
return newindex;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException("This method should never be called");
}
}
}
Then, make it known in your XAML:
//(declare a namespace in your window tag:)
xmlns:myNamespace="clr-namespace:MyNameSpace"
// add:
<Window.Resources>
<ResourceDictionary>
<myNamespace:IndexConverter x:Key="indexConverter" />
</ResourceDictionary>
</Window.Resources>
Then change your binding:
<ComboBox SelectedIndex="{Binding SC.User1.UserID, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource indexConverter}}" ... />
That should do the trick. At least you can debug it by inserting a breakpoint in the IndexConverter.

Resources