WPF ComboBox数据绑定未更新

时间:2018-08-01 21:36:43

标签: c# wpf

如图所示,我有一个组合框,向我显示了我数据库中的所有事件。例如,这可能是生日聚会。 Listview正在向我显示参与者。这一切都完美无缺。但是,当我在运行的应用程序中添加新事件时,使用文本框和按钮“ Toevoegen”(翻译为“添加”),我的组合框未显示新事件。当我重新启动程序时,它确实显示了它。

我发现这与属性更改有关。但是,当我将项目添加到eventmanager.events.Add(item)的实例时,该如何使用呢?

enter image description here

Xaml

<Window x:Class="Databinding.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:Databinding"
        mc:Ignorable="d"
        Title="Events" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ComboBox x:Name="cbEvents1" ItemsSource="{Binding events, Mode=TwoWay}" SelectedItem="{Binding currentEvent}" SelectedValuePath="Content" Margin="10,10,31.667,381.667">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <ListView Grid.Column="1" ItemsSource="{Binding participants}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding firstName}"/>
                    <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding lastName}"/>
                </GridView>
            </ListView.View>
        </ListView>
        <Label Content="Nieuw evenement " HorizontalAlignment="Left" Margin="10,53,0,0" VerticalAlignment="Top"/>
        <Label Content="Naam:" HorizontalAlignment="Left" Margin="44,80,0,0" VerticalAlignment="Top" RenderTransformOrigin="1.083,0.564"/>
        <TextBox x:Name="tbNaamEv" HorizontalAlignment="Left" Height="23" Margin="93,79,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="272"/>
        <Label x:Name="lblOmschrijving1" Content="Omschrijving:" HorizontalAlignment="Left" Margin="10,115,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="TbOmschrijvingEV" HorizontalAlignment="Left" Height="23" Margin="93,119,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="272"/>
        <Label Content="Opmerking:" HorizontalAlignment="Left" Margin="21,151,0,0" VerticalAlignment="Top"/>
        <Label Content="Datum:" HorizontalAlignment="Left" Margin="46,186,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tbOpmerkingEv" HorizontalAlignment="Left" Height="23" Margin="93,154,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="205"/>
        <Button x:Name="btnAdd1" Content="Toevoegen" HorizontalAlignment="Left" Margin="207,234,0,0" VerticalAlignment="Top" Width="158" Height="24" Click="btnAdd_Click"/>
        <DatePicker x:Name="DPevenement" HorizontalAlignment="Left" Margin="93,189,0,0" VerticalAlignment="Top" Width="205" FirstDayOfWeek="Monday" IsDropDownOpen="True"/>
        <Label Content="Evenement informatie" HorizontalAlignment="Left" Margin="6,270,0,0" VerticalAlignment="Top"/>
        <Label Content="Omschrijving:" HorizontalAlignment="Left" Margin="6,301,0,0" VerticalAlignment="Top"/>
        <Label x:Name="lblOmschrijvingEv" Content="{Binding omschrijving}" HorizontalAlignment="Left" Margin="93,301,0,0" VerticalAlignment="Top" Width="294" Height="26"/>
        <Label Content="Opmerking:" HorizontalAlignment="Left" Margin="16,344,0,0" VerticalAlignment="Top"/>
        <Label x:Name="lblOpmerkingEv" Content="{Binding opmerking}" HorizontalAlignment="Left" Margin="93,344,0,0" VerticalAlignment="Top" Width="294" Height="26"/>
        <Label Content="Datum:" HorizontalAlignment="Left" Margin="40,385,0,0" VerticalAlignment="Top"/>
        <Label x:Name="lblDatumEv" Content="{Binding Datum}" HorizontalAlignment="Left" Margin="93,385,0,0" VerticalAlignment="Top" Width="294" Height="26"/>
    </Grid>
</Window>

Eventmanager类

public class EventManager : INotifyPropertyChanged
{
    public List<Event> events { get; set; }
    public List<People> peoples { get; set; }

    //this is the current event that correspond to the selected event in your combobox
    private Event _currentEvent;
    public Event currentEvent
    {
        get
        {
            return _currentEvent;
        }
        set
        {
            if (_currentEvent != value)
            {
                _currentEvent = value;
                //when you change the selected event, you have to update the list of participants
                OnPropertyChanged("participants");
            }
        }
    }

    public List<People> participants
    {
        get
        {
            //Here is the code to retrieve the people that registered to the selected event
            return peoples.Where(p => p.registeredEvents.Contains(currentEvent)).ToList<People>();
        }
    }

    public EventManager()
    {
        events = new List<Event>();
        peoples = new List<People>();
    }

    //The following lines are specific to WPF and DataBinding
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }


}

人民阶层

public class People : INotifyPropertyChanged
{
    public string firstName { get; set; }
    public string lastName { get; set; }

    public List<Event> registeredEvents { get; set; }

    public People()
    {
        registeredEvents = new List<Event>();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

public class Event : INotifyPropertyChanged
{
    public string name { get; set; }
    public string omschrijving { get; set; }
    public string opmerking { get; set; }
    public DateTime Datum { get; set; }



    //The following lines are specific to WPF and DataBinding
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

}

这是我添加活动和参与者的方式:

    EventManager eventManager = new EventManager();
    DBConnect connect = new DBConnect();
    public Event Selected;

private void btnAdd_Click(object sender, RoutedEventArgs e)
    {

        connect.EvToevoegen(tbNaamEv.Text, TbOmschrijvingEV.Text, tbOpmerkingEv.Text, Convert.ToDateTime(DPevenement.SelectedDate));

        Selected = new Event()
        {
            name = tbNaamEv.Text
        };

        eventManager.events.Add(Selected);

    }
}

新活动不会显示在我的组合框中吗?

2 个答案:

答案 0 :(得分:1)

列表不会像您期望的那样响应PropertyChanged事件,因为列表本身可能从未更改。它的内容确实存在。

要使ItemsSource响应集合更改,该集合必须实现INotifyCollectionChanged接口。值得庆幸的是,C#为我们提供了已经实现该接口的集合。

如果您使用ObservableCollection<T>,则可以立即获得此功能。

尝试更换:

public List<Event> events { get; set; }

使用:

public ObservableCollection<Event> events { get; set; }


如果由于某种原因无法更改此集合的类型,则需要以某种方式包装列表。

最简单的方法是使用可观察集合公开的副本构造函数:

new ObservableCollection<T>(IEnumerable<T>)

答案 1 :(得分:0)

首先,您的People类正在实现INotifyPropertyChanged,但实际上没有任何属性在提高OnPropertyChanged(除非您使用的是Caliburn之类的框架或自动实现它的东西)。

不过,要回答您的问题,您的registeredEvents属性需要实现INotifyCollectionChanged,例如类型为ObservableCollection<Event>。但是,当您在数据库之间进行序列化时,这会带来一些潜在的问题,因为如果数据库层返回一个List,并将其转换为ObservableCollection,那么当您再次保存它时,数据库将认为整个列表已更改,然后重新序列化整个序列,而不管是否有任何实际更改。显然,这会严重影响性能。

如何最好地解决此问题将取决于应用程序的其他部分。您可以选择将ObservableCollection分开,然后在用户完成操作后将其与原始列表进行比较,并一次性更新原始列表。许多ORM允许您控制它们创建的数据结构的类型,在这种情况下,可以使它们为所有列表创建ObservableCollections,而这个问题首先就不存在。您的视图模型层可以选择将两个列表都保留在内存中,并在运行时从这两个列表中添加/删除元素,一次是为了数据库的利益,而另一个是为了视图。另外,如果您的列表很小,则只要继续对列表进行任何更改,就可以继续使用List<Element>,提高OnPropertyChanged("registeredEvents")并解决重新创建所有列表GUI元素的性能问题。自己。