将IsEnabled绑定到自定义类型集合的属性并刷新触发器

时间:2015-10-27 13:05:02

标签: wpf binding model-binding

我有一个窗口,其中包含一个包含多个项目的列表框。有一个itemtemplate定义它们应该由一个复选框表示:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
             xmlns:converters="clr-namespace:WpfApplication1.Converters"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid MouseLeftButtonDown="Grid_MouseLeftButtonDown">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListBox ItemsSource="{Binding Customers}" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item.Name}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Grid.Row="1"
                HorizontalAlignment="Right"
                Margin="5"
                Content="Test"
                IsEnabled="{Binding Customers, Converter={converters:CustomersToBoolConverter}}"
                />
    </Grid>
</Window>

接下来,我在后面的代码中声明绑定的'Customers'集合及其项目,如下所示:

public partial class MainWindow : Window,  INotifyPropertyChanged
{
    public ObservableCollection<CheckedListItem<Customer>> Customers { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;


    public MainWindow()
    {
        InitializeComponent();
        Customers = new ObservableCollection<CheckedListItem<Customer>>();
        Customers.Add(new CheckedListItem<Customer>(new Customer() { Name = "Kelly Smith" }));
        Customers.Add(new CheckedListItem<Customer>(new Customer() { Name = "Joe Brown" }));
        Customers.Add(new CheckedListItem<Customer>(new Customer() { Name = "Herb Dean" }));
        Customers.Add(new CheckedListItem<Customer>(new Customer() { Name = "John Paul" }));

        DataContext = this;
    }

     void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Customers"));

    }
}

以下是Customer类定义:

public class Customer
{
    public string Name { get; set; }
}

以下是CheckedListItem类的定义:

public class CheckedListItem<T> : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isChecked;
    private T item;

    public CheckedListItem()
    { }

    public CheckedListItem(T item, bool isChecked = false)
    {
        this.item = item;
        this.isChecked = isChecked;
    }

    public T Item
    {
        get { return item; }
        set
        {
            item = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
        }
    }


    public bool IsChecked
    {
        get { return isChecked; }
        set
        {
            isChecked = value;                
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
        }
    }

后者实现了我的INPC逻辑。

我将按钮的状态绑定到Customers列表和转换器的输出,如果检查了任何项目,则返回true。

在加载窗口时效果很好,但是,如果我检查列表中的任何项目,则没有任何反应。此外,如果我在MainWindow类中实现INPC逻辑并显式调用

if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Customers"));

然后,通知被发送到我的窗口,按钮的状态就更新了。

我的问题是如何从CheckedListItem中发送此通知,是否可能?

代码来源:http://www.jarloo.com/how-to-create-a-checkedlistbox-in-wpf/

1 个答案:

答案 0 :(得分:0)

您可以绑定CollectionChanged ObservableCollection事件,该事件在添加,删除,更改,移动项目或刷新整个列表时发生。

您可以将事件订阅代码放在MainWindow构造函数

Customers.CollectionChanged += Customers_CollectionChanged;

代码中的处理程序:

void Customers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            /// Your code
        }