C# NotifyPropertyChanged,仅当事件绑定到命令时查看更新
我对c#和WPF还是相当陌生的,所以也许这是意料之中的,但我觉得很奇怪,我似乎无法摆脱它 我有一个窗口,其中有一个区域可以输入有关事件的信息,还有一个提交按钮以及一些绑定到可观察集合的C# NotifyPropertyChanged,仅当事件绑定到命令时查看更新,c#,wpf,mvvm,inotifypropertychanged,icommand,C#,Wpf,Mvvm,Inotifypropertychanged,Icommand,我对c#和WPF还是相当陌生的,所以也许这是意料之中的,但我觉得很奇怪,我似乎无法摆脱它 我有一个窗口,其中有一个区域可以输入有关事件的信息,还有一个提交按钮以及一些绑定到可观察集合的数据网格。该按钮绑定到我的viewmodel上的一个命令,当输入一个新事件时,我对可观察的集合进行一些更改,并且更新视图上的数据网格 问题在于编辑其中一个数据网格上的单元格时。我已经尝试将celleditended事件绑定到视图模型上的命令,因此我尝试使用代码隐藏事件处理程序以不同的方式进行绑定。我将所需的编辑信息
数据网格。该按钮绑定到我的viewmodel上的一个命令,当输入一个新事件时,我对可观察的集合进行一些更改
,并且更新视图上的数据网格
问题在于编辑其中一个数据网格
上的单元格时。我已经尝试将celleditended
事件绑定到视图模型上的命令,因此我尝试使用代码隐藏事件处理程序以不同的方式进行绑定。我将所需的编辑信息传递给viewmodel,以与上面工作方式完全相同的方式对可观察集合进行更改,并且可以看到可观察集合中的更改,但视图不会更新。notifypropertychange
不会启动,notifycollectionchange
也不会启动
那么为什么observateCollection
在事件通过命令时似乎只触发属性或集合更改来更新视图呢
完整代码如下:
主窗口视图的XAML代码;这个例子就是我从中得到xcdg:CellEditorBinding位的地方
<Window.Resources>
<DataTemplate x:Key="DateTextblock">
<TextBlock Text="{Binding StringFormat={}{0:D}}"/>
</DataTemplate>
<xcdg:DataGridCollectionViewSource x:Key="HistoryViewSource" Source="{Binding History, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<xcdg:DataGridCollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Date" Direction="Descending"/>
</xcdg:DataGridCollectionViewSource.SortDescriptions>
</xcdg:DataGridCollectionViewSource>
<ViewModel:MainWindowViewModel x:Key="MainWindowCollections"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<!--Account Balances and Spending goals-->
<RowDefinition Height="Auto"/>
<!--History-->
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<!--Account Balances-->
<ColumnDefinition x:Name="AccountsWidth" Width="Auto"/>
<!--Categorized spending goals-->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<xcdg:DataGridControl x:Name="AccountsDataGrid"
ItemsSource="{Binding Accounts, UpdateSourceTrigger=PropertyChanged}"
AutoCreateColumns="False"
SelectionMode="Single"
FontSize="14"
Height="Auto"
Width="Auto">
<xcdg:DataGridControl.Columns>
<xcdg:Column Title="Account" FieldName="Name">
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<TextBox x:Name="AccountText" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnSourceUpdated=True}" Style="{StaticResource MainTextboxStyle}" MinWidth="100"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
<xcdg:Column Title="Balance" FieldName="Balance">
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<xctk:DecimalUpDown Value="{Binding Balance, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnSourceUpdated=True}" Style="{StaticResource DecimalUpDownStyle}"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
<xcdg:DataGridControl Grid.Row="1" Height="Auto" x:Name="HistoryDataGrid" ItemsSource="{Binding Source={StaticResource HistoryViewSource}, UpdateSourceTrigger=PropertyChanged}" AutoCreateColumns="False" SelectionMode="Single" FontSize="14" xcdg:Cell.EditEnded="HistoryDataGrid_EditEnded">
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding TransactionEditCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>-->
<xcdg:DataGridControl.Columns>
<xcdg:Column Title="ID" FieldName="ID" Visible="False"/>
<xcdg:Column Title="Type" FieldName="Type"/>
<xcdg:Column Title="Amount" FieldName="Amount">
<xcdg:Column.CellContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding StringFormat={}{0:C}, NotifyOnSourceUpdated=True}"/>
</DataTemplate>
</xcdg:Column.CellContentTemplate>
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<xctk:DecimalUpDown Value="{xcdg:CellEditorBinding NotifyOnSourceUpdated=True}" Style="{StaticResource DecimalUpDownStyle}"/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>
视图模型代码
public class MainWindowViewModel : GalaSoft.MvvmLight.ObservableObject
{
public MainWindowViewModel()
{
Accounts = DatabaseFunctions.getAccountData();
History = DatabaseFunctions.getHistoryData();
}
private ObservableCollection<AccountsModel> accounts;
public ObservableCollection<AccountsModel> Accounts
{
get { return accounts; }
set
{
accounts = value;
RaisePropertyChanged("Accounts");
}
}
private ObservableCollection<HistoryModel> history;
public ObservableCollection<HistoryModel> History
{
get { return history; }
set
{
history = value;
RaisePropertyChanged("History");
History.CollectionChanged += History_CollectionChanged;
}
}
public ICommand HistoryEditCommand
{
get { return new ParamDelegateCommand<RoutedEventArgs>(HistoryCellEdit); }
}
public void HistoryCellEdit(RoutedEventArgs e)
{
UpdateAccountData("Chequing", 200);
}
public void UpdateAccountData(string AccountName, decimal NewBalance)
{
var item = Accounts.FirstOrDefault(i => i.Name == AccountName);
if (item != null)
{
item.Balance = NewBalance;
}
}
void Accounts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (AccountsModel item in e.NewItems)
item.PropertyChanged += Accounts_PropertyChanged;
if (e.OldItems != null)
foreach (AccountsModel item in e.OldItems)
item.PropertyChanged -= Accounts_PropertyChanged;
}
void History_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (HistoryModel item in e.NewItems)
item.PropertyChanged += History_PropertyChanged;
if (e.OldItems != null)
foreach (HistoryModel item in e.OldItems)
item.PropertyChanged -= History_PropertyChanged;
}
void Accounts_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
void History_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
}
这个历史模型
public class HistoryModel : ObservableObject
{
#region Properties
private Double id;
public Double ID
{
get { return id; }
set
{
id = value;
RaisePropertyChangedEvent("ID");
}
}
private string type;
public string Type
{
get { return type; }
set
{
type = value;
RaisePropertyChangedEvent("Type");
}
}
private decimal amount;
public decimal Amount
{
get { return amount; }
set
{
amount = value;
RaisePropertyChangedEvent("Amount");
}
}
}
通知属性已更改
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
将代码添加到model、viewmodel和相关xaml中。这表明您的模型没有实现INotifyPropertyChanged
。如果元素的属性发生更改,ObseravbleCollection
不会通知视图,除非元素也实现了接口。似乎缺少信息。类别是可观察的集合吗?如果是这样,这些项目本身是否可以观察到?@zaitsman我已经添加了一个分类模型。简而言之,每一个模型的每一个元素都有其本质的变化。UpdateCategoryData位于视图模型中。每当我需要更改Categories observable集合中的值时,就会调用它。至于xaml代码,我甚至不知道哪部分是相关的,但我添加了数据网格位。谢谢您的帮助。@glenebob Categories是可观察的集合,并且模型(据我所知)实现了notifyproperty更改;我已经添加了类别模型的一部分。感谢您的帮助。那么您使用什么绑定从datagrid列到对象属性?将代码添加到model、viewmodel和相关xaml。这表明您的模型没有实现INotifyPropertyChanged。如果元素的属性发生更改,ObseravbleCollection
不会通知视图,除非元素也实现了接口。似乎缺少信息。类别是可观察的集合吗?如果是这样,这些项目本身是否可以观察到?@zaitsman我已经添加了一个分类模型。简而言之,每一个模型的每一个元素都有其本质的变化。UpdateCategoryData位于视图模型中。每当我需要更改Categories observable集合中的值时,就会调用它。至于xaml代码,我甚至不知道哪部分是相关的,但我添加了数据网格位。谢谢您的帮助。@glenebob Categories是可观察的集合,并且模型(据我所知)实现了notifyproperty更改;我已经添加了类别模型的一部分。感谢您的帮助。那么您使用什么绑定从datagrid列到对象属性?将代码添加到model、viewmodel和相关xaml。这表明您的模型没有实现INotifyPropertyChanged。如果元素的属性发生更改,ObseravbleCollection
不会通知视图,除非元素也实现了接口。似乎缺少信息。类别是可观察的集合吗?如果是这样,这些项目本身是否可以观察到?@zaitsman我已经添加了一个分类模型。简而言之,每一个模型的每一个元素都有其本质的变化。UpdateCategoryData位于视图模型中。每当我需要更改Categories observable集合中的值时,就会调用它。至于xaml代码,我甚至不知道哪部分是相关的,但我添加了数据网格位。谢谢您的帮助。@glenebob Categories是可观察的集合,并且模型(据我所知)实现了notifyproperty更改;我已经添加了类别模型的一部分。感谢您的帮助那么您使用什么绑定从datagrid列到对象属性呢?
public class HistoryModel : ObservableObject
{
#region Properties
private Double id;
public Double ID
{
get { return id; }
set
{
id = value;
RaisePropertyChangedEvent("ID");
}
}
private string type;
public string Type
{
get { return type; }
set
{
type = value;
RaisePropertyChangedEvent("Type");
}
}
private decimal amount;
public decimal Amount
{
get { return amount; }
set
{
amount = value;
RaisePropertyChangedEvent("Amount");
}
}
}
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}