Reputation: 171
I am trying to understand the concept of DataBinding a combobox with an object.
I have the following class:
public class employmentApplication
{
private byte appType = 0; // 1 = normal; 2 = expedited
public byte AppType
{
get { return appType ; }
set
{
appType = value;
this.OnPropertyChanged("AppType");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
My xaml for the combobox is
<ComboBox>
<ComboBoxItem Content="Normal" />
<ComboBoxItem Content="Expedited" />
</ComboBox>
I am not sure where to begin to bind my combobox to the AppType since it has to convert it from a string ("Normal", "Expedited") to a byte (0, 1) and back between the object and the combobox.
Thanks for any help in advance!
Upvotes: 1
Views: 7022
Reputation: 1239
You could do this several ways, however here is a simple solution todo what you have asked. Note, your DataContext
will need to be set to your instance of the class you want to represent.
<ComboBox SelectedValue="{Binding AppType, Mode=TwoWay}"
SelectedValuePath="Tag">
<ComboBoxItem Content="Normal" Tag="0"/>
<ComboBoxItem Content="Expedited" Tag="1"/>
</ComboBox>
SelectedValue
is binded to your property, and SelectedValuePath is the property of ComboBoxItem
(in this case) that will represent the selected value.
This is a very simple solution, and you may need to alter it for your needs. Additionally, I would consider using an Enum
to represent this data. It will make it a little easier to understand what you are trying todo in code.
Edit
Here is an example of using an enum
with the above example. I'm going to use your already existing code as a base.
Create an enum (preferably in a new file).
public enum AppType
{
Normal,
Expedited
}
Now modify your property to use the enum
public AppType AppType
{
get
{
return appType;
}
set
{
if( Equals( appType, value ) ) return;
appType = value;
OnPropertyChanged( "AppType" );
}
}
Now you can use my above example, but with an enum:
<ComboBox SelectedValue="{Binding AppType, Mode=TwoWay}"
SelectedValuePath="Tag">
<ComboBoxItem Content="Normal" Tag="{x:Static local:AppType.Normal}"/>
<ComboBoxItem Content="Expedited" Tag="{x:Static local:AppType.Expedited"/>
</ComboBox>
The following is nice for having a little more control over what is displayed in the ComboBox
. However you can also have it display every enum
value, which is nice because if you add enum
values in the future, they will automatically show up in the ComboBox
. See this question and answer for a way of doing that.
Upvotes: 3
Reputation: 6415
You could use a converter, or tags, as the other answers have shown. But you could also define your item-source as a class rather than rely on hand-waving to link integers to strings. So your item source items could be a class like this:
public class AppType
{
public string Name;
public byte Type;
}
You can then use SelectedValue and SelectedValuePath binding on your combobox to define what changes in your datacontext, and what property is used in the lookup list.
<ComboBox
ItemSource = {Binding ListOfAppTypes}
SelectedValue="{Binding Type, Mode=TwoWay}"
SelectedValuePath="Name">
</ComboBox>
You could also define a Template for your Combobox where you gain more control over how the lookup list of items is displayed.
Upvotes: 0
Reputation: 1136
My advice is to use ValueConverter. It's more flexable solution than using Tag values and it's looks nice because you are separating conversion logic in its own class. Also I noticed that in your data class you declared PropertyChanged event but not implemented INotifyPropertyChanged interface so you can't have two way binding in this case. Full example:
Your data class (with my fixes)
public class EmploymentApplication : INotifyPropertyChanged
{
private byte appType = 0; // 1 = normal; 2 = expedited
public byte AppType
{
get { return appType; }
set
{
appType = value;
OnPropertyChanged("AppType");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
Value converter
public class AppTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var b = (byte)value;
if (b == 1) return "Normal";
if (b == 2) return "Expedited";
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var strValue = (string) value;
byte result = 0;
if (strValue.Equals("Normal", StringComparison.Ordinal))
{
result = 1;
}
else if (strValue.Equals("Expedited", StringComparison.OrdinalIgnoreCase))
{
result = 2;
}
return result;
}
}
xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new EmploymentApplication();
}
}
Xaml
<Window x:Class="WpfConvertion.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfConvertion"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:AppTypeConverter x:Key="Converter"></local:AppTypeConverter>
</Window.Resources>
<Grid>
<ComboBox Height="20" SelectedValue="{Binding AppType, Converter={StaticResource Converter}}" SelectedValuePath="Content">
<ComboBoxItem>Normal</ComboBoxItem>
<ComboBoxItem>Expedited</ComboBoxItem>
</ComboBox>
</Grid>
Pay attention on this line: xmlns:local="clr-namespace:WpfConvertion". You must set your own namespace here instead of my WpfConvertion.
Upvotes: 1
Reputation: 13755
There are several ways to achieve this the simplest could be to add a bind to your AppType with SelectedIndex property of your ComboBox
Note that you should add INotifyPropertyChanged
to let your binding work
and in code behind do the following
namespace WpfApplication8
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
employmentApplication emp = new employmentApplication();
public MainWindow()
{
InitializeComponent();
this.DataContext = emp;
}
}
public class employmentApplication:INotifyPropertyChanged
{
private byte appType = 0; // 1 = normal; 2 = expedited
public byte AppType
{
get { return appType; }
set
{
appType = value;
this.OnPropertyChanged("AppType");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
}
Upvotes: 0
Reputation: 432
The simplest way is, if yout Normal value is 0 and your Expedited value is 1, use SelectedIndex to bind to.
<ComboBox SelectedIndex="{Binding AppType}" >
Upvotes: 0