WPF ItemsControl 元素 DataTrigger 在数据更改后不会触发
WPF ItemsControl element DataTrigger doesn`t fire after data changes
我遇到了这样一个问题:我的数据触发器在绑定数据更改后没有更改颜色。 Datatrigger 在 TextBlock 上,它是 ItemsControl 的 ElemntTenplate。
我的Xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition Height="3*"></RowDefinition>
</Grid.RowDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding TaresToReturn, StringFormat='К возврату: {0}'}"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding TaresReturned, StringFormat='Возвращено: {0}'}"></TextBlock>
</Grid>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Visible">
<ItemsControl ItemsSource="{Binding Tares}" Margin="5">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="tareReturnController:p_GetTaresForReturnResult">
<Border Width="100" Height="30" Margin="10">
<TextBlock x:Name="TextBlock" Text="{Binding barcode}" FontSize="15">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsReturned, UpdateSourceTrigger=PropertyChanged}" Value="false">
<Setter Property="TextBlock.Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsReturned, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="TextBlock.Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<!--<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsReturned}" Value="false">
<Setter TargetName="TextBlock" Property="TextBlock.Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsReturned}" Value="true">
<Setter TargetName="TextBlock" Property="TextBlock.Background" Value="Green"/>
</DataTrigger>
</DataTemplate.Triggers>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
我的 ViewModel 部分:
private ObservableCollection<p_GetTaresForReturnResult> tares_;
public ObservableCollection<p_GetTaresForReturnResult> Tares
{ get { return tares_; } set { tares_ = value; } }
private void GetTares()
{
tares_ = new ObservableCollection<p_GetTaresForReturnResult>(Terminal.Dc.p_GetTaresForReturn(DateTime.Parse("05.05.2015")));
}
public int TaresToReturn
{ get { return Tares.Count(t => Convert.ToBoolean(t.IsReturned) == false); } }
public int TaresReturned
{ get { return Tares.Count(t => Convert.ToBoolean(t.IsReturned)); } }
public void ScannerOnOnBarcodeReceived(string[] _args)
{
foreach (string barcode in _args)
{
var tt = Tares.FirstOrDefault(t => t.barcode.ToLower().Trim() == barcode.ToLower().Trim());
if (tt != null)
{
var ttt = new p_GetTaresForReturnResult();
ttt.barcode = "111";
ttt.id = 111;
ttt.IsReturned = false;
tares_.Add(ttt);//Add new element for test
tt.IsReturned = true;
tt.barcode = "1";
RaisePropertyChanged("TaresToReturn");
RaisePropertyChanged("TaresReturned");
RaisePropertyChanged("barcode");
RaisePropertyChanged("IsReturned");
RaisePropertyChanged("Tares");
}
}
}
代码p_GetTaresForReturnResult
public partial class p_GetTaresForReturnResult
{
private int _id;
private string _barcode;
private System.Nullable<bool> _IsReturned;
public p_GetTaresForReturnResult()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_id", DbType="Int NOT NULL")]
public int id
{
get
{
return this._id;
}
set
{
if ((this._id != value))
{
this._id = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_barcode", DbType="NChar(20)")]
public string barcode
{
get
{
return this._barcode;
}
set
{
if ((this._barcode != value))
{
this._barcode = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_IsReturned", DbType="Bit")]
public System.Nullable<bool> IsReturned
{
get
{
return this._IsReturned;
}
set
{
if ((this._IsReturned != value))
{
this._IsReturned = value;
}
}
}
}
第一次加载页面时,我的元素颜色正确。
当我更改集合并调用 RaisePropertyCahnged 时,它们不会更改颜色!
注意:如果我将新元素添加到集合中,它会出现在 WrapPanel 中。但是已经创建的项目不会改变它们的颜色和文本!
谁能告诉我我做错了什么?
如果你想顺利处理这个,我认为你必须用一个 NotificatonObject
包装这个 class,其中包含一个 p_GetTaresForReturnResult
字段和 writes/reads 属性,但它在 setter 中调用 RaisePropertyChanged
。
否则您需要替换 项以通知视图有关更改。
由 Messenger 编辑:
我修改了 p_GetTaresForReturnResult class:
public partial class p_GetTaresForReturnResult : INotifyPropertyChanged
{
...
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_IsReturned", DbType="Bit")]
public System.Nullable<bool> IsReturned
{
get
{
return this._IsReturned;
}
set
{
if ((this._IsReturned != value))
{
this._IsReturned = value;
NotifyPropertyChanged("IsReturned");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我遇到了这样一个问题:我的数据触发器在绑定数据更改后没有更改颜色。 Datatrigger 在 TextBlock 上,它是 ItemsControl 的 ElemntTenplate。
我的Xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition Height="3*"></RowDefinition>
</Grid.RowDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding TaresToReturn, StringFormat='К возврату: {0}'}"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding TaresReturned, StringFormat='Возвращено: {0}'}"></TextBlock>
</Grid>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Visible">
<ItemsControl ItemsSource="{Binding Tares}" Margin="5">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="tareReturnController:p_GetTaresForReturnResult">
<Border Width="100" Height="30" Margin="10">
<TextBlock x:Name="TextBlock" Text="{Binding barcode}" FontSize="15">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsReturned, UpdateSourceTrigger=PropertyChanged}" Value="false">
<Setter Property="TextBlock.Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsReturned, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="TextBlock.Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<!--<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsReturned}" Value="false">
<Setter TargetName="TextBlock" Property="TextBlock.Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsReturned}" Value="true">
<Setter TargetName="TextBlock" Property="TextBlock.Background" Value="Green"/>
</DataTrigger>
</DataTemplate.Triggers>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
我的 ViewModel 部分:
private ObservableCollection<p_GetTaresForReturnResult> tares_;
public ObservableCollection<p_GetTaresForReturnResult> Tares
{ get { return tares_; } set { tares_ = value; } }
private void GetTares()
{
tares_ = new ObservableCollection<p_GetTaresForReturnResult>(Terminal.Dc.p_GetTaresForReturn(DateTime.Parse("05.05.2015")));
}
public int TaresToReturn
{ get { return Tares.Count(t => Convert.ToBoolean(t.IsReturned) == false); } }
public int TaresReturned
{ get { return Tares.Count(t => Convert.ToBoolean(t.IsReturned)); } }
public void ScannerOnOnBarcodeReceived(string[] _args)
{
foreach (string barcode in _args)
{
var tt = Tares.FirstOrDefault(t => t.barcode.ToLower().Trim() == barcode.ToLower().Trim());
if (tt != null)
{
var ttt = new p_GetTaresForReturnResult();
ttt.barcode = "111";
ttt.id = 111;
ttt.IsReturned = false;
tares_.Add(ttt);//Add new element for test
tt.IsReturned = true;
tt.barcode = "1";
RaisePropertyChanged("TaresToReturn");
RaisePropertyChanged("TaresReturned");
RaisePropertyChanged("barcode");
RaisePropertyChanged("IsReturned");
RaisePropertyChanged("Tares");
}
}
}
代码p_GetTaresForReturnResult
public partial class p_GetTaresForReturnResult
{
private int _id;
private string _barcode;
private System.Nullable<bool> _IsReturned;
public p_GetTaresForReturnResult()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_id", DbType="Int NOT NULL")]
public int id
{
get
{
return this._id;
}
set
{
if ((this._id != value))
{
this._id = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_barcode", DbType="NChar(20)")]
public string barcode
{
get
{
return this._barcode;
}
set
{
if ((this._barcode != value))
{
this._barcode = value;
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_IsReturned", DbType="Bit")]
public System.Nullable<bool> IsReturned
{
get
{
return this._IsReturned;
}
set
{
if ((this._IsReturned != value))
{
this._IsReturned = value;
}
}
}
}
第一次加载页面时,我的元素颜色正确。 当我更改集合并调用 RaisePropertyCahnged 时,它们不会更改颜色! 注意:如果我将新元素添加到集合中,它会出现在 WrapPanel 中。但是已经创建的项目不会改变它们的颜色和文本!
谁能告诉我我做错了什么?
如果你想顺利处理这个,我认为你必须用一个 NotificatonObject
包装这个 class,其中包含一个 p_GetTaresForReturnResult
字段和 writes/reads 属性,但它在 setter 中调用 RaisePropertyChanged
。
否则您需要替换 项以通知视图有关更改。
由 Messenger 编辑: 我修改了 p_GetTaresForReturnResult class:
public partial class p_GetTaresForReturnResult : INotifyPropertyChanged
{
...
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_IsReturned", DbType="Bit")]
public System.Nullable<bool> IsReturned
{
get
{
return this._IsReturned;
}
set
{
if ((this._IsReturned != value))
{
this._IsReturned = value;
NotifyPropertyChanged("IsReturned");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}