简体   繁体   中英

WPF: Databinding ComboBox to int value

I have a class like this:

public class Service
{
    public int State { get; set; }
}

How can I bind it to a ComboBox so the combo shows "Active"/"Inactive" and the State becomes 1 or 0?

<ComboBox SelectedItem="{Binding Path=State}">
    <ComboBoxItem Content="Active" Tag="1" IsSelected="True"/>
    <ComboBoxItem Content="Inactive" Tag="0" />
</ComboBox>

I'm binding the object to the form using DataContext form.DataContext = new Service();

First of all, Tag attribute just holds whatever data you give it, it has no contribution to binding of SelectedItem. If ComboBoxItems have no datacontext, you might be able to do this, give it a try:

<ComboBox SelectedValue="{Binding Path=State}" SelectedValuePath="Tag">
    <ComboBoxItem Content="Active" Tag="1" IsSelected="True"/>
    <ComboBoxItem Content="Inactive" Tag="0" />
</ComboBox>

usually you would use a value converter , but in this scenario you can easily use a dictionary.

Something like this should work:

public class Service
{
   public Dictionary<int,string> StateDictonary {get;set;}

    public Service()
    {
      StateDictonary = new Dictionary<int,string>();
      StateDictonary[1] = "Active";
      StateDictonary[0] = "Inactive";
    }
}

Then in the xaml you would do something like:

<ComboBox ItemsSource="{Binding StateDictonary }"   DisplayMemberPath="Value" SelectedValuePath="Key" />

I'm at home now, so I can't test this. so let me know if it doesn't work

There are a number of ways to do this:

  1. A bit of a hack, but you could just reverse the order of your items and bind to SelectedIndex instead of SelectedItem. This, of course, doesn't work if you need different numbers or need that specific order.

  2. Instead of statically declaring the two options, you could have a list of "State" objects with a string and int property in your view model. You would then set the ItemsSource of the combo box to this collection, and your "State" property in the view model changes to this new type. You would set the "DisplayMemberPath" property of the combo box to the string property. Then you can just get the int out of the SelectedItem. This is probably the most easily extensible solution. You could even use an enum instead of an int (more readable).

  3. Make the "State" property an object (or even a String) and in it's setter, check against your two labels. Depending on which label it is, set the "real" int property to the correct value.

Personally, I would go the second route if you think you might ever have another state, and use the enum instead of a straight int. I can provide an example if you would like.

You want to create an object as the ItemsSource for your ComboBox . Since you defined the items in the ComboBox , the underlying data type is a ComboBoxItem for its ItemsSource and doing a binding against the SelectedItem it will map it to the underlying datatype. Since you are trying to data bind a value that is int which is not the data type for the combobox's ItemsSource that won't work.

To do this, I would do something like this

public class Service
{
    private State _selectedState;
    private readonly ObservableCollection<State> _states = new ObservableCollection<State>() { new State() { Value = "Active", IsSelected = true} ,new State() {Value = "Inactive" }};

    public State SelectedSelectedState
    {
        get { return _selectedState; }
        set
        {
            _selectedState = value;
            BitState = _selectedState.Value == "Active" ? 1 : 0;
        }
    }

    public int BitState { get; set; }

    public class State
    {
        public bool IsSelected { get; set; }
        public string Value { get; set; }
    }

    public ObservableCollection<State> States
    {
        get { return _states; }
    }
}

And on MainWindow

public MainWindow()
{
 InitializeComponent();
 comboBox.DataContext = new Service();
}

If you don't want it this control then you can do something like this,

    public enum State
    {
        Inactive,
        Active,
    }

    public class Service
    {
        private readonly ObservableCollection<State> _states = new ObservableCollection<State>() { State.Inactive, State.Active };
        private int _selectedValue;

        public int SelectedValue
        {
            get { return _selectedValue; }
            set { _selectedValue = value; }
        }

        public ObservableCollection<State> States
        {
            get { return _states; }
        }
    }

And your XAML

    <ComboBox x:Name="blah" SelectedIndex="{Binding Path=SelectedValue, Mode=TwoWay}" ItemsSource="{Binding States}"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM