如图所示,我有一个组合框,向我显示了我数据库中的所有事件。例如,这可能是生日聚会。 Listview正在向我显示参与者。这一切都完美无缺。但是,当我在运行的应用程序中添加新事件时,使用文本框和按钮“ Toevoegen”(翻译为“添加”),我的组合框未显示新事件。当我重新启动程序时,它确实显示了它。
我发现这与属性更改有关。但是,当我将项目添加到eventmanager.events.Add(item)的实例时,该如何使用呢?
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);
}
}
新活动不会显示在我的组合框中吗?
答案 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元素的性能问题。自己。