WPF Data Binding to a Combo Box

2020-07-30 00:59发布

I am new to WPF, C# and data binding. I am just trying to bind a simple combo box to an ObservedCollection. Here is the code:

 public class Directory
{
    private string _ikey;
    public string IKey
    {
        get
        {
            return _ikey;
        }
        set
        {
            _ikey = value;
        }
    }
    private string _ivalue;
    public string IValue
    {
        get
        {
            return _ivalue;
        }
        set
        {
            _ivalue = value;
        }
    }

}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window

{
    public ObservableCollection<Directory> DirectoryList = new ObservableCollection<Directory>();

    public MainWindow()
    {
        InitializeComponent();

        DirectoryList = new ObservableCollection<Directory>();
        Directory _dirtemp = new Directory();
        _dirtemp.IKey = "1";
        _dirtemp.IValue = "Steve";
        DirectoryList.Add(_dirtemp);

        _dirtemp = new Directory();
        _dirtemp.IKey = "2";
        _dirtemp.IValue = "John";
        DirectoryList.Add(_dirtemp);




    }
}

My xaml looks like this:

<Window x:Class="DataBindCombo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DataBindCombo"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ComboBox Height="48" HorizontalAlignment="Left" Margin="70,104,0,0" Name="comboBox1" VerticalAlignment="Top" Width="310"
              ItemsSource="{Binding Path=DirectoryList}"
              DisplayMemberPath="IValue"
              SelectedValuePath="IKey"
              >

It seems like it should be simple. I was able to put the binding in the code behind and it worked fine, but I would like to have it bind through xaml.

Any ideas? TIA

5条回答
劫难
2楼-- · 2020-07-30 01:40

Point the binding to your code behind:

ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DirectoryList}"
查看更多
Rolldiameter
3楼-- · 2020-07-30 01:42

What you need to do is set the ComboBox's DataContext equal to your ObservableCollection.

Code-behind:

  public partial class MainWindow : Window
{
    private ObservableCollection<Directory> directoryList;

    public MainWindow()
    {
        InitializeComponent();

        directoryList = new ObservableCollection<Directory>();
        Directory _dirtemp = new Directory();
        _dirtemp.IKey = "1";
        _dirtemp.IValue = "Steve";
        directoryList.Add(_dirtemp);

        _dirtemp = new Directory();
        _dirtemp.IKey = "2";
        _dirtemp.IValue = "John";
        directoryList.Add(_dirtemp);

        this.comboBox1.DataContext = DirectoryList;
        //OR for the entire window you can simply do this.DataContext = DirectoryList;
    }

    public ObservableCollection<Directory> DirectoryList
    {
        get { return directoryList; }
    } 
}

public class Directory
{
    private string _ikey;
    public string IKey
    {
        get
        {
            return _ikey;
        }
        set
        {
            _ikey = value;
        }
    }
    private string _ivalue;
    public string IValue
    {
        get
        {
            return _ivalue;
        }
        set
        {
            _ivalue = value;
        }
    }

}

Xaml:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="84" Width="167">
<Grid>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding}"/>
</Grid>

Though, as others had noted, a better approach would be using the Model-View-ViewModel design pattern. This will keep the View (xaml part) separate from the "the business logic" . Here is a good example on how to bind a comboBox using MVVM.

http://mark-dot-net.blogspot.com/2009/03/binding-combo-boxes-in-wpf-with-mvvm.html

查看更多
做自己的国王
4楼-- · 2020-07-30 01:43

Paths in a binding are with respect to the local DataContext, not the containing Window. You have not set a DataContext for your Window, so WPF does not have an object on which to look up the DirectoryList property.

With your current object model, you need to set this.DataContext = this; in your MainWindow constructor. Now the MainWindow object will be the DataContext, and the DirectoryList binding will be resolved against the MainWindow object. (Longer term, a better practice is to move the data model out to a separate class, and set the DataContext to an instance of that class, but that's a separate issue.)

Also, WPF can bind only to properties, not fields. Your DirectoryList attribute is currently a field; you will need to change it to a property.

查看更多
Lonely孤独者°
5楼-- · 2020-07-30 01:55

You need to set the DataContext of the window. For example like this:

public MainWindow()
{
    InitializeComponent();
    DataContext = this;
     ....
}
查看更多
霸刀☆藐视天下
6楼-- · 2020-07-30 02:01

There are a couple ways you can go about this. The basics are you need to make it so the XAML can see your collection. You can do this in an implicit manner by setting it to your DataContext. If this is the only thing you are binding then its a quick and dirty way of binding. It would look like this:

public partial class MainWindow : Window

{
    public ObservableCollection<Directory> DirectoryList;

    public MainWindow()
    {
        InitializeComponent();

        DirectoryList = new ObservableCollection<Directory>();
        Directory _dirtemp = new Directory();
        _dirtemp.IKey = "1";
        _dirtemp.IValue = "Steve";
        DirectoryList.Add(_dirtemp);

        _dirtemp = new Directory();
        _dirtemp.IKey = "2";
        _dirtemp.IValue = "John";
        DirectoryList.Add(_dirtemp);


        DataContext=DirectoryList;

    }
}

Window x:Class="DataBindCombo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DataBindCombo"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ComboBox Height="48" HorizontalAlignment="Left" Margin="70,104,0,0" Name="comboBox1" VerticalAlignment="Top" Width="310"
              ItemsSource="{Binding}"
              DisplayMemberPath="IValue"
              SelectedValuePath="IKey"
              >

The other way is more sophisticated but probably what you will use more often. To do it You need to expose your collection in your MainWindow as a DependencyProperty and then bind to that value. It would look something like this:

public partial class MainWindow : Window
    {
        public static DependencyProperty DirectoryListProperty =
            DependencyProperty.Register("DirectoryList",
            typeof(ObservableCollection<Directory>),
            typeof(MainWindow));

        public MainWindow()
        {
            InitializeComponent();
        }

        public ObservableCollection<Directory> DirectoryList
        {
            get { return (ObservableCollection<Directory>)base.GetValue(DirectoryListProperty); }
            set { base.SetValue(DirectoryListProperty, value); }
        }
    }

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" x:Name="mainWindow">
    <Grid>
        <ComboBox Height="48" HorizontalAlignment="Left" Margin="70,104,0,0" Name="comboBox1" VerticalAlignment="Top" Width="310"
              ItemsSource=" {Binding ElementName=mainWindow, Path=DirectoryList}"
              DisplayMemberPath="IValue"
              SelectedValuePath="IKey"
              />

This is also not the only way to accomplish it in this manner. In general rather than creating the list directly on the control you would create a view model. The MVVM pattern is the recommend way of creating your presentation, but my examples give you a way of getting functionality out there. You can play and experiment with different ways of doing this. I've discovered there are always multiple ways of doing things in WPF and its a matter of finding the one that fits the situation the best.

查看更多
登录 后发表回答