WPF:ListBox和ComboBox的绑定

时间:2012-11-15 18:59:14

标签: wpf xaml binding

我通过书籍学习WPF中的绑定。我写了这样的代码:

using System;

namespace WpfBinding {
    enum SomeColors {
        Red,
        Green,
        Blue,
        Gray
    }
}

using System;

namespace WpfBinding {
    class TestItem {
        SomeColors color;

        public TestItem(SomeColors color) {
            Color = color;
        }
        internal SomeColors Color {
            get { return color; }
            set { color = value; }
        }
        public override string ToString() {
            return Color.ToString();
        }
    }
}

我的窗口的XAML:

<Window x:Class="WpfBinding.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">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListBox x:Name="listBox" HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch" Margin="5"/>
        <ComboBox x:Name="comboBox" HorizontalAlignment="Stretch" 
                  VerticalAlignment="Top" Margin="5" Grid.Column="1"/>
    </Grid>
</Window>

我尝试通过代码创建绑定:

using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfBinding {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            // Data for listbox
            TestItem[] items = new TestItem[] {
                new TestItem(SomeColors.Red), 
                new TestItem(SomeColors.Green), 
                new TestItem(SomeColors.Green), 
                new TestItem(SomeColors.Red), 
                new TestItem(SomeColors.Blue), 
                new TestItem(SomeColors.Red), 
            };
            // Create ObservableCollection item
            ObservableCollection<TestItem> collection = new ObservableCollection<TestItem>(items);
            listBox.ItemsSource = collection;// set data for listbox

            comboBox.ItemsSource = Enum.GetValues(typeof(SomeColors)); // Get items from my enum

            // Create bindings
            Binding bind = new Binding();
            bind.Source = listBox;
            bind.Path = new PropertyPath("SelectedItem.Color");
            bind.Mode = BindingMode.TwoWay;
           comboBox.SetBinding(ComboBox.SelectedItemProperty, bind);
        }
    }
}

但是我的绑定没有用。为什么?

屏幕: enter image description here

4 个答案:

答案 0 :(得分:2)

认为问题在于您的课程没有实施INotifyPropertyChanged

为了让绑定知道某个属性何时更改了它的值,您必须向其发送通知,然后使用INotifyPropertyChanged执行此操作。

<强>更新

因此,您的列表框绑定到ObservableCollection,它确实提供了更改通知,但到列表框中,并且只有在您添加或删除集合中的项目时才会这样。

您可能还想在visual studio(http://msdn.microsoft.com/en-us/library/dd409960%28v=vs.100%29.aspx)中启用WPF绑定跟踪信息,这可能有助于您弄清楚发生了什么。

我注意到的最后一件事是TestItem类的Color属性标记为internal。 WPF将无法访问该属性,除非它是public

答案 1 :(得分:2)

在调试时观察Visual Studio的“输出”窗口总是很有用!如果你看过那里,你会看到这个:

System.Windows.Data Error: 40 : BindingExpression path error: 'Color' property not found on 'object' ''TestItem' (HashCode=20856310)'. BindingExpression:Path=SelectedItem.Color; DataItem='ListBox' (Name='listBox'); target element is 'ComboBox' (Name='comboBox'); target property is 'SelectedItem' (type 'Object')

确切地说,只能使用公共属性进行绑定,所以

internal SomeColors Color

应该是

public SomeColors Color

答案 2 :(得分:2)

这是错误 -

System.Windows.Data Error: 40 : BindingExpression path error: 'Color' property
not found on 'object' ''TestItem' (HashCode=13974362)'.  
BindingExpression:Path=SelectedItem.Color; DataItem='ListBox' (Name='listBox');
target element is 'ComboBox' (Name='comboBox'); target property is 'SelectedItem'
(type 'Object')

您需要设置属性Color public而不是internal

来自MSDN here -

  

您用作绑定的绑定源属性的属性必须   是你班级的公共财产。明确定义的接口   无法访问属性用于绑定目的,也不能保护,   没有基础的私有,内部或虚拟属性   实施

答案 3 :(得分:1)

谢谢大家。我编辑了我的代码:

using System;
using System.ComponentModel;

namespace WpfBinding {
    public class TestItem : INotifyPropertyChanged{
        SomeColors color;

        public TestItem(SomeColors color) {
            Color = color;
        }
        public SomeColors Color {
            get { return color; }
            set { color = value;
            OnPropertyChanged("Color");
                 }
        }
        public override string ToString() {
            return Color.ToString();
        }

        void OnPropertyChanged(String name) {
            PropertyChangedEventHandler temp = PropertyChanged;
            if (null != temp) {
                temp(this, new PropertyChangedEventArgs(name));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfBinding {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            // Data for listbox
            TestItem[] items = new TestItem[] {
                new TestItem(SomeColors.Red), 
                new TestItem(SomeColors.Green), 
                new TestItem(SomeColors.Green), 
                new TestItem(SomeColors.Red), 
                new TestItem(SomeColors.Blue), 
                new TestItem(SomeColors.Red), 
            };
            // Create ObservableCollection item
            ObservableCollection<TestItem> collection = new ObservableCollection<TestItem>(items);
            listBox.ItemsSource = collection;// set data for listbox

            ObservableCollection<SomeColors> collection2 = new 
                ObservableCollection<SomeColors>(Enum.GetValues(typeof(SomeColors)).Cast<SomeColors>());
            comboBox.ItemsSource = collection2; // Get items from my enum
            // Create bindings
            Binding bind = new Binding();
            bind.Source = listBox;
            bind.Path = new PropertyPath("SelectedItem.Color");
            bind.Mode = BindingMode.TwoWay;
           comboBox.SetBinding(ComboBox.SelectedItemProperty, bind);
        }
    }
}

请看屏幕,请: enter image description here