我刚刚回到WPF/XAML编程中,遇到了一个我无法解决的问题。我有一个对象,可以将其视为一个订单,每个订单包含一个Store对象列表,每个Store包含一个Planogram对象列表。未处理的订单从数据库中检索出来,并放入一个可观察的集合中。
使用MVVM工具包时,每个属性都使用INotify来指示属性的更改时间。这还会设置IsDirty标志,以指示已进行更改。Store对象和Order对象都有一个附加到子列表的集合更改事件的事件处理程序,以指示某些包含的元素已更改。
视图模型包含可观察的订单集合,并且还有一个关于该列表的集合更改事件的事件处理程序,因此表单可以更新。
该窗体有一个列表框,其中包含订单的名称。选定订单后,详细信息将显示在窗体的其他控件上。
这是背景...问题在这里...我在列表框的项目模板中为每个订单名称设置了一个文本块。使用BoolToVis转换器将可见性绑定到Is Dirty标志。如果我选择了一个订单并更改了任何子属性,这些改变会被传递到父文件,并且修改标志被正确设置。2但是源文件不会被更新,文本框中的“*”也不会被显示。
但是,可以选择添加空白订单。创建空白订单并将其添加到订单列表中。此时,新订单显示在列表框中,订单名称旁边带有 *。
我已经搜索了几天,阅读了所有我能在SO上找到的东西。我看到的大多数情况是,人们没有在酒店上安装INotify。我安装了,我找到的每个答案都说这应该是有效的......但事实并非如此。
包含IsDirty标志的基对象
public class BaseOneOffStorePlanogram : ObservableObject, IOneOffData
{
private bool _isDirty = false;
public bool IsDirty
{
get { return _isDirty; }
set {
if(value != _isDirty)
{
_isDirty = value;
base.OnPropertyChanged("IsDirty");
}
}
}
public string LastModifiedBy { get; set; }
public DateTime? LastModifiedOn { get; set; }
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (e.PropertyName != "IsDirty")
{
base.OnPropertyChanged(e);
IsDirty = true;
}
}
}
这是Store对象的一个片段,其中每个属性都调用OnPropertyChanged事件,并且我还在其中连接了Collection changed。
public string StoreNumber
{
get { return _StoreNumber; }
set
{
_StoreNumber = value;
base.OnPropertyChanged("StoreNumber");
}
}
public DateTime? PricingDateOverride
{
get
{
return _PricingDateOverride;
}
set
{
_PricingDateOverride = value;
base.OnPropertyChanged("PricingDateOverride");
}
}
public OneOffStore()
{
_OneOffStorePlanograms = new ObservableCollection<OneOffStorePlanogram>();
_OneOffStorePlanograms.CollectionChanged += _OneOffStorePlanograms_CollectionChanged;
}
private void _OneOffStorePlanograms_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.OldItems != null)
{
foreach( OneOffStorePlanogram oosp in e.OldItems)
{
oosp.PropertyChanged += InvokeCollectionChanged;
}
}
if( e.NewItems != null)
{
foreach(OneOffStorePlanogram oosp in e.NewItems)
{
oosp.PropertyChanged += InvokeCollectionChanged;
}
}
}
private void InvokeCollectionChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("OneOffStorePlanograms");
}
这是视图模型中定义可观察集合的部分
public ObservableCollection<OneOff> OneOffs
{
get { return _oneOffs; }
}
private void InitializeForm(){
_oneOffs = new ObservableCollection<OneOff>();
_selectedStores = new ObservableCollection<Store>();
_selectedPlanograms = new ObservableCollection<Models.Planogram>();
_useEffectiveDate = false;
LoadPlanograms();
LoadStores();
LoadOneOffs();
//GetUnprocessedOneOffs();
_oneOffs.CollectionChanged += OneOffs_CollectionChanged;`
}
这是XAML代码段
<ListBox x:Name="lstActiveJobs" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding OneOffs, NotifyOnSourceUpdated=True,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedOneOff}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding OneOffName, PresentationTraceSources.TraceLevel=High}" Grid.Row="0" Grid.Column="0" />
<TextBlock Text="*" x:Name="HasChangeModifier" Grid.Row="0" Grid.Column="1" Visibility="{Binding IsDirty, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我确信这是简单的事情,或者我做错了。让我困惑的是,新添加的,未保存的项目工作,但从数据库检索的项目不工作。
任何建议都将不胜感激。
1条答案
按热度按时间xkftehaa1#
被重写的
OnPropertyChanged(PropertyChangedEventArgs e)
方法不为IsDirty
属性调用base.OnPropertyChanged(e)
,因此不通知到该属性的绑定。该方法应如下所示:
请注意,
OnPropertyChanged(PropertyChangedEventArgs e)
由OnPropertyChanged(string propertyName)
调用。需要注意的是,使用CommunityToolkit.MVVM,您不需要自己编写属性声明,只需使用
ObservableProperty
属性即可: