0

我通过书在 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);
        }
    }
}

但是我的绑定不起作用。为什么?

屏幕: 在此处输入图像描述

4

4 回答 4

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.

于 2012-11-15T19:07:26.403 回答
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
于 2012-11-15T19:21:54.407 回答
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 -

用作绑定的绑定源属性的属性必须是类的公共属性。不能出于绑定目的访问显式定义的接口属性,也不能访问没有基本实现的受保护、私有、内部或虚拟属性。

于 2012-11-15T19:26:38.837 回答
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);
        }
    }
}

请看屏幕: 在此处输入图像描述

于 2012-11-15T19:42:27.980 回答