【问题标题】:WPF Data Binding to a Combo BoxWPF 数据绑定到组合框
【发布时间】:2011-04-26 14:17:02
【问题描述】:

我是 WPF、C# 和数据绑定的新手。我只是想将一个简单的组合框绑定到 ObservedCollection。代码如下:

 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);




    }
}

我的 xaml 看起来像这样:

<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"
              >

看起来应该很简单。我能够将绑定放在后面的代码中并且效果很好,但我希望通过 xaml 进行绑定。

有什么想法吗? TIA

【问题讨论】:

    标签: c# wpf data-binding


    【解决方案1】:

    有几种方法可以解决这个问题。基础是您需要制作它,以便 XAML 可以看到您的集合。您可以通过将其设置为 DataContext 以隐式方式执行此操作。如果这是您唯一要绑定的东西,那么它是一种快速而肮脏的绑定方式。它看起来像这样:

    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"
                  >
    

    另一种方法更复杂,但可能您会更经常使用。为此,您需要将 MainWindow 中的集合作为 DependencyProperty 公开,然后绑定到该值。它看起来像这样:

    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"
                  />
    

    这也不是以这种方式完成它的唯一方法。通常,与其直接在控件上创建列表,不如创建一个视图模型。 MVVM pattern 是创建演示文稿的推荐方式,但我的示例为您提供了一种获取功能的方式。您可以尝试并尝试不同的方法。我发现在 WPF 中总是有多种做事方式,而问题在于找到最适合这种情况的方式。

    【讨论】:

      【解决方案2】:

      绑定中的路径与本地 DataContext 相关,而不是包含 Window。您尚未为 Window 设置 DataContext,因此 WPF 没有可在其上查找 DirectoryList 属性的对象。

      使用您当前的对象模型,您需要在 MainWindow 构造函数中设置this.DataContext = this;。现在 MainWindow 对象将成为 DataContext,DirectoryList 绑定将针对 MainWindow 对象进行解析。 (从长远来看,更好的做法是将数据模型移到单独的类中,并将 DataContext 设置为该类的实例,但这是一个单独的问题。)

      此外,WPF 只能绑定到属性,不能绑定到字段。您的 DirectoryList 属性当前是一个字段;您需要将其更改为属性。

      【讨论】:

        【解决方案3】:

        您需要做的是设置 ComboBox 的 DataContext 等于您的 ObservableCollection。

        代码隐藏:

          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>
        

        不过,正如其他人所指出的,更好的方法是使用 Model-View-ViewModel 设计模式。这将使视图(xaml 部分)与“业务逻辑”分开。这是一个关于如何使用 MVVM 绑定组合框的好例子。

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

        【讨论】:

          【解决方案4】:

          您需要设置窗口的DataContext。比如这样:

          public MainWindow()
          {
              InitializeComponent();
              DataContext = this;
               ....
          }
          

          【讨论】:

            【解决方案5】:

            将绑定指向您背后的代码:

            ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DirectoryList}"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-10-07
              • 1970-01-01
              • 2015-12-12
              • 2014-02-03
              • 2011-08-25
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多