【发布时间】:2016-05-30 05:43:00
【问题描述】:
我正在使用版本 2.4.14475.10340 中的“Xceed Extended WPF Tookit Plus (Complete”) Edition 和生产软件环境中工具包的 DataGrid。
目前我正在努力让突出显示的数据行再次工作。
a.) 网格的数据源是一个标准的 DataTable,所以像下面这样的自定义 DataRow 样式确实对我有用:
<Style TargetType="{x:Type xcdg:DataRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=[IsTrend]}" Value="True">
<Setter Property="Background" Value="Gold"/>
</DataTrigger>
</Style.Triggers>
</Style>
由于基础数据的动态特性,我们将源类型更改为“ExpandoObject”,并在其字典形式中使用它来添加/删除数据条目,然后使用字段名称将其映射到数据网格列。更改后上述样式不再起作用,错误见下文:
Cannot get 'Item[]' value (type 'Object') from '' (type 'ExpandoObject'). BindingExpression:Path=[IsTrend]; DataItem='ExpandoObject' (HashCode=34521593); target element is 'DataRow' (Name=''); target property is 'NoTarget' (type 'Object') TargetInvocationException:'System.Reflection.TargetInvocationException
b.) 作为一种解决方法,我们将样式更改为自定义转换器:
<Style TargetType="{x:Type xcdg:DataRow}">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource HighlightingConverter}}"/>
</Style>,
它返回一个 Brush,取决于 DataRow 项 (DataGrid.GetItemFromContainer(row)) 的字段值,因此是 ExpandoObject。
现在数据网格中的行有时会着色,但 a.) 不正确(错误的行)或 b.) 刷新数据后颜色变松。看起来数据行容器已着色,然后重新用于新数据。
我的问题:
- 为什么它适用于 a.) 中的上述样式,但如果我使用像 b.) 中的自定义转换器则不能?使用“[]”语法访问哪个字段或路径?
- 有没有办法为动态数据源实现行照明?
/编辑: 源集合如下所示。
private ObservableCollection<dynamic> GetDynamicOrders2()
{
var retVal = new ObservableCollection<dynamic>();
for (int i = 0; i < 50; i++)
{
dynamic eo = new ExpandoObject();
eo.Name = new CellContent("Order" + i);
eo.IsTrend = new CellContent(i % 2 == 0);
var converted = (IDictionary<string, object>)eo;
converted["Number"] = new CellContent(i % 4);
converted["NumberDouble"] = new CellContent((double)i);
converted["properties_name_first"] = new CellContent("Name " + i);
retVal.Add(eo);
}
return retVal;
}
一个单元格对象定义为:
public sealed class CellContent : INotifyPropertyChanged
{
private object _value;
public object Value
{
get { return _value; }
set
{
if (Equals(value, _value)) return;
_value = value;
OnPropertyChanged();
OnPropertyChanged("DisplayValue");
OnPropertyChanged("BackgroundColor");
OnPropertyChanged("ForegroundColor");
}
}
public bool Meta { get; set; }
public string Format { get; set; }
public double Threshold { get; set; }
public string DisplayValue
{
get
{
return string.Format(string.Format("{{0:{0}}}", Format), Value);
}
}
public SolidColorBrush BackgroundColor
{
get
{
var defaultColor = new SolidColorBrush(Colors.Transparent);
var valueType = Value.GetType();
if (valueType != typeof (double)) return defaultColor;
if (double.IsNaN(Threshold)) return defaultColor;
return (double)Value >= Threshold ? new SolidColorBrush(Colors.Red) : defaultColor;
}
}
public SolidColorBrush ForegroundColor
{
get
{
var defaultColor = new SolidColorBrush(Colors.Black);
var valueType = Value.GetType();
if (valueType != typeof(double)) return defaultColor;
// inactive
if (double.IsNaN(Threshold)) return defaultColor;
return (double)Value >= Threshold ? new SolidColorBrush(Colors.Blue) : defaultColor;
}
}
public CellContent(object value, bool meta = false, string format = "", double threshold = double.NaN)
{
Value = value;
Meta = meta;
Format = format;
Threshold = threshold;
}
private bool Equals(CellContent other)
{
return Equals(Value, other.Value);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CellContent)obj);
}
public override int GetHashCode()
{
return (Value != null ? Value.GetHashCode() : 0);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
/Edit2: 如果我使用显式路径,绑定错误:
System.Windows.Data Error: 40 : BindingExpression path error: 'IsTrend' property not found on 'object' ''MainWindow' (Name='')'. BindingExpression:Path=IsTrend; DataItem='MainWindow' (Name=''); target element is 'DataRow' (Name=''); target property is 'NoTarget' (type 'Object')
/Edit3:解决方案。 整个问题在于我添加样式的方式。与上面的问题一样,我全局定义了样式,因此它应用于此用户控件/窗口中的每个单个 DataRow 对象。这导致了“MainWindow”的数据上下文,这当然在这里没有更大的用处。 我将样式更改为(已添加键,已更正路径)
<Style TargetType="{x:Type xcdg:DataRow}" x:Key="RowStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsTrend.Value}" Value="True">
<Setter Property="Background" Value="Gold"/>
</DataTrigger>
</Style.Triggers>
</Style>
并像这样从数据网格中添加了一个引用
<xcdg:DataGridControl x:Name="DataGrid" ItemContainerStyle="{StaticResource RowStyle}">
完成。它再次起作用了!
非常感谢所有帮助。
提前致谢, 尼科·埃克
【问题讨论】:
-
您已将背景绑定到 Self 含义 DataRow。由于滚动时DataRow没有刷新,所以刷新(基本上是虚拟化的行容器原因)。如果您能够提供源代码集合以及上述代码,那么提供解决方案将很容易。或者我必须随意制作一个。您的简单解决方案目标应该是绑定源集合类型的属性,这样行颜色就可以完美地工作。
-
我不确定我是否理解您的评论,但我会将有关源集合的信息添加到原始问题中。
-
检查答案...please.let me know if you face some questions
-
我再次更新了这个问题,提供了一个解决方案,该解决方案部分由你的工作组成,谢谢你,以及我自己的见解。
-
我有点困惑。你还有问题吗?它是什么?
标签: c# wpf data-binding