我在C#中使用新的WPF Viewer for Crystal Reports。当我使用MVVM时,我真的想要绑定要显示的数据源而不是在加载的事件中执行此操作。因此,我想为源实现附加属性 - 但绑定不起作用,甚至不调用Getter方法。关于绑定附加属性的其他帖子也没有帮助,我不确定我在做什么不同。有人可以帮忙吗?这是附加属性的简化代码:
public static class CrystalReportsAttached {
public static readonly DependencyProperty SourceProperty =
DependencyProperty.RegisterAttached(
"Source",
typeof(IEnumerable),
typeof(CrystalReportsAttached),
new UIPropertyMetadata(new ObservableList<Participant>() as IEnumerable, SourceChanged));
public static void SetSource(DependencyObject target, IEnumerable value) {
target.SetValue(SourceProperty, value);
}
public static IEnumerable GetSource(DependencyObject target) {
return (IEnumerable)target.GetValue(SourceProperty);
}
private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
CrystalReportsViewer reportViewer = d as CrystalReportsViewer;
if (reportViewer != null) {
MyCrystalReport report = new MyCrystalReport();
report.SetDataSource(d.GetValue(SourceProperty) as IEnumerable);
reportViewer.ViewerCore.ReportSource = report;
}
}
}
其中MyCrystalReport
是我的rpt报告文件的包装器。
如果我现在这样绑定到源,它就不起作用了:
<my:CrystalReportsViewer prop:CrystalReportsAttached.Source="{Binding MyList, Mode=OneWay}"/>
我尝试以同样的方式绑定DataGrid
s ItemsSource
,这样就可以了,所以路径名称或smth似乎没有错误。
非常感谢任何帮助。非常感谢!
答案 0 :(得分:2)
使用依赖项属性,您可以确定的是,当属性发生更改时,将调用属性更改的回调,并且实际更改基础属性如果调用了getter。这可能看起来很奇怪但是你的getter和setter只是访问那个底层属性,所以如果XAML解析器调用target.GetValue(SourceProperty)
它就会得到正确的东西,而不会调用你的getter。
真正的问题是您的属性是否更改了回调被调用?
答案 1 :(得分:1)
要接收对集合的更改,源集合必须实现INotifyCollectionChanged。
您可以使用ObservableCollection,在线查找自定义通知集合,或使用您编写的实现内部集合和INotifyCollectionChanged接口的类包装现有集合。
如果初始绑定失败,请检查您是否已将DataContext(设置为View-Model),VM上的属性名称正确以及该属性具有公共getter。
编辑:
这部分错了:
new UIPropertyMetadata(new ObservableList<Participant>() as IEnumerable, SourceChanged));
您正在将相同的列表实例设置为所有控件的默认值。 改为在构造函数中设置默认值(在DP注册行中放置null)。
答案 2 :(得分:0)
我终于找到了问题所在:
似乎CrystalReportViewer
的DataContext由于某种原因被覆盖。因此,绑定在每个其他上下文中工作(例如在DataGrid
中),但不在此处。我使用上面snoop提到的default.kramer工具找到了问题。我可以通过将绑定更改为
<my:CrystalReportsViewer prop:CrystalReportsAttached.Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.Participants, Mode=OneWay}"/>
所以它确实访问DataContext
的{{1}}(通常应该与特定控件的UserControl
相同,但不适用于CrystalReportsViewer
)并且它现在正在运行
感谢大家的帮助!