自定义属性依赖于其他属性
对于事件式的解释提前表示歉意;我认为有很多因素都各自发挥着作用。 WPF 不是我选择的本机框架,这可能表明了这一点。 :)
旧情况:我有一个带有多个控件的窗口。根据他们的选择,我使用多重绑定和转换器来确定是否需要显示某些控件,以便在用户最终通过“确定”确认(或通过使用“取消”简单地取消)之前通知用户其更改的影响。这非常有效。
问题:随着时间的推移,控制太多,太混乱。 解决方案:将内容放在不同的页面中,以便用户更容易浏览。为了让用户在页面之间任意浏览时保留更改,我动态创建这些更改并将它们放入缓存中(Dictionary
结果:我需要解耦与通知控件的绑定,因为不同的选项现在位于不同的页面上。
解决方案?我放置了一个 BasePage 类,该类公开了某些抽象只读属性,这些属性定义了窗口为了执行通知而需要了解的各个方面。例如,bool requiresReboot 属性定义该页面上的当前状态是否需要重新启动才能(完全)生效。特定页面根据其控件实现该属性。 问题:我不知道如何继续创建正确的绑定,以便在页面更改时正确更新。我尝试使用检查所有页面和相关属性的转换器将通知控件绑定到 Dictionary
。
问题:
1)我如何为此目的创建合适的属性?我想我需要一个 DependancyProperty,因为我在 MSDN 上阅读了大量内容,但我无法弄清楚它是如何组合在一起的。 2) 如何在自定义属性之间建立链接,以便允许页面上的(多个)控件更改该属性?我是否以某种方式使用INotifyPropertyChanged
?我的旧示例绑定了 XAML 中的多个 CheckBox.IsChecked
属性。我试图避免在控件上放置大量事件(OnChange 等),因为原始代码不需要它,而且我被告知就 WPF 而言,它会导致一个混乱的解决方案。 3)最后,我怀疑我可能需要将我的 Dictionary
类更改为实现某种 INotifyPropertyChanged
但对于集合的自定义实现?我相信可观察集合是我正在寻找的术语。
我希望有人能够弥补我对 WPF(属性)内部结构的理解上的差距;我将非常感激。一个基本的示例会更好,但如果太复杂,只需朝正确的方向轻推即可。谢谢。 :)
Advance apologies for the event-style explanation; there's a lot of factors that I feel all play a role of their own. WPF is not my native framework of choice, and it probably shows. :)
Old situation: I had a window with several controls. Depending on their selections, I used multibindings and a converter to determine whether certain controls needed to be shown that inform the user about the implications of their changes before they'd eventually confirm them by OK (or simply dismissed by using Cancel). This worked perfectly.
Problem: Too many controls as time went by, too much clutter.
Solution: Put stuff in different Pages so it becomes easier to browse for the user. In order to have changes-to-be persist as a user arbitrarily browses between the pages, I create these dynamically and put them in a cache (Dictionary<string, BasePage>
, see below), from which they will be pulled as the user chooses them.
Consequence: I need to decouple the bindings to the notification controls as the different options are now on different pages.
Solution? I put a BasePage
class in that exposes certain abstract read-only properties that define the various aspects that the window needs to know about in order to do its notifications. For example, a bool requiresReboot
property defines whether the current state of things on that page requires a reboot to take (full) effect. A specific page implements the property based on its controls.
Problem: I do not know how to keep create a proper binding that properly gets updated as the pages are changed. I tried giving my notification controls a binding to the Dictionary<string, BasePage>
with a converter that checks all pages and the relevant property.
Questions:
1) How do I create a proper property for this purpose? I presume I need a DependancyProperty
as I did a fair bit of reading on MSDN, but I can't figure out how this fits together.
2) How do I make a link between my custom property so that it allows (multiple) control(s) on a page to change that property? Do I use INotifyPropertyChanged
somehow? My old example bound against several CheckBox.IsChecked
properties in XAML. I am trying to avoid putting tons of events (OnChange, etc) on the controls as the original code did not need it and I have been told it makes for a messy solution for as far WPF is concerned.
3) Finally, I suspect I may need to change my Dictionary<string, BasePage>
class to a custom implementation that implements some sort of INotifyPropertyChanged
but for Collections? Observable Collection is the term I am looking for, I believe.
I hope someone is able to bridge the gap in my understanding of WPF (property) internals; I would very much appreciate it. A basic sample would be even better, but if it is too complicated, just a nudge in the right direction will do. Thank you. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我解决这个问题已经有一段时间了,虽然我不记得问题的确切原因,但有几个不同的问题构成了我遇到的大部分麻烦。
我最终将相关属性设置为基类中的非抽象
DependencyProperty
;这是我可以正确地将更改通知委托给界面的唯一方法。派生类最终只是将其绑定到其控件(在需要额外逻辑的情况下使用适当的Converter
)。由于
Dictionary
不支持任何类型的更改通知,因此我创建了一个额外的ObservableCollection
集合,用于绑定目的。但是,当其中的项目的属性发生更改时,此类集合不会传播更改事件。由于这种情况需要这样做,并且我在一个属性的上下文中绑定到集合本身,该属性没有像
DataGrid
这样的 Master<->Detail 关系(它基本上添加了自己的OnPropertyChanged
处理程序到绑定对象),我最终对VeryObservableCollecton
进行了子类化。这个监听它自己的项目,并抛出一个适当的更改事件(我认为它是来自INotifyPropertyChanged
接口的OnPropertyChanged
),以便绑定(或者在本例中是一个多重绑定)将正确刷新并允许我的界面更新。它不是最漂亮的代码,而且感觉设计过度,但至少它允许我以这种方式正确地将 UI 绑定到数据。
It's been a while since I solved this, and while I cannot remember the exact cause of the problems, there were a few different issues that made up the bulk of the trouble I ran into.
I ended up making the Property in question a non-abstract
DependencyProperty
in the base class; it was the only way in which I could properly delegate the change notifications to the interface. Derived classes simply ended up binding it to their controls (with a properConverter
in the case extra logic was necessitated).As
Dictionary<string, BasePage>
does not support any sort of change notification, I made an extra collection ofObservableCollection<BasePage>
which I used for binding purposes.However, such a collection does not propagate a change event when items inside of it has a property changed. Since this situation required that, and I was binding to the collection itself in the context of a property that does not have a Master<->Detail relationship like a
DataGrid
(which basically add their ownOnPropertyChanged
handlers to the binded object), I ended up subclassing aVeryObservableCollecton<>
. This one listens to its own items, and throws a proper change event (I think it was anOnPropertyChanged
from theINotifyPropertyChanged
interface) so that the binding (or in this case a multi-binding) would refresh properly and allow my interface to update.It is hardly the prettiest code, and it feels over-engineered, but at least it allows me to properly bind the UI to the data in this manner.