[英]How to access non-bindable view properties from the view model?
I'm using the Telerik WPF RadGanttView
control to display a bunch of data. 我正在使用Telerik WPF
RadGanttView
控件来显示大量数据。 Since the data can be arbitrarily weird - events that are instantaneous, or that last days, or have a week between them - it's not possible to set a PixelLength
(ie a scale factor) that's guaranteed to be useful. 由于数据可能是任意奇怪的-瞬时事件,持续时间或最后几天或事件之间有一周的时间-不可能设置保证有用的
PixelLength
(即比例因子)。 I've been asked to make it possible to change this scale factor with a slider. 我被要求使用滑块来更改此比例因子。 Unfortunately, just changing the scale factor with the slider has a usability issue, which I need to fix by manually adjusting where the view is scrolled.
不幸的是,仅使用滑块更改比例因子会带来可用性问题,我需要通过手动调整视图的滚动位置来解决。 I'm at a loss as to how exactly.
我不知道该怎么做。
To outline the usability problem I'm fixing: the view works by providing a "viewport", located at an "offset", over the whole "extent" of the data set. 为了概述我要解决的可用性问题:该视图通过在数据集的整个“范围”内的“偏移”处提供一个“视口”来工作。 (Terms lifted from the Telerik API . These seem to simply represent pixels in the canvas underlying the scrollable view.) When the scale factor goes from, say, 100% to 200% (which corresponds to halving the
PixelLength
), what happens is that the width of the extent is doubled, but the horizontal offset
remains the same. (从Telerik API提起的术语。这些似乎只是表示可滚动视图下面的画布中的像素。)当比例因子从100%变为200%(相当于将
PixelLength
减半)时,会发生什么事情? 程度的宽度加倍,但水平offset
保持相同。 The consequence is that after zooming in, it's quite likely you'll see entirely different data than before, since the events that were there before got "pulled out" of the viewport to the right. 结果是放大后,很有可能您会看到与以前完全不同的数据,因为之前存在的事件被“拉出”了右侧的视口。
The way I intend to fix this is: grab the offset/viewport/extent etc before zooming in, zoom, then do some maths I haven't figured out yet with that and the new offset/viewport/extent. 我打算解决的方法是:在放大,缩放之前获取偏移量/视口/范围等,然后进行一些我还没有弄清楚的数学运算以及新的偏移量/视口/范围。 The problem is: the properties of
RadGanttView
that describe the scrolling stuff are not DependencyProperty
s, and I cannot simply bind them to properties on my ViewModel
. 问题是:描述滚动内容的
RadGanttView
的属性不是 DependencyProperty
,并且我不能简单地将它们绑定到ViewModel
属性。 (In fact, they're not even accessible in XAML to begin with, RadGanttView
implements IScrollingInfo
explicitly.) (事实上,他们甚至还没有在XAML访问开始,
RadGanttView
实现IScrollingInfo
明确。)
So, my question is: how do I, in my ViewModel
, or wherever else in reaction to the ViewModel
's scale factor changing, access properties of a control in the corresponding View
, that cannot be data-bound? 因此,我的问题是:如何在我的
ViewModel
,或者响应ViewModel
的缩放因子变化的其他地方,如何访问相应View
控件的属性,而该属性不能是数据绑定的? Every search I tried tells me that accessing the view from the viewmodel is "not MVVM", but since Telerik is a third-party library, I can't really refactor how this works on their side. 我尝试进行的每一次搜索都告诉我,从viewmodel访问视图是“不是MVVM”,但是由于Telerik是第三方库,因此我无法真正重构它在它们方面的工作方式。
A fill-in-the-blanks outline of my code: 我的代码的空白处概述:
class FooViewModel
{
// A slider in the view pushes its value into this property
double ScaleFactor
{
get { /*...*/ }
set
{
PixelLength = GetNewPixelLength(value);
// ...
}
}
// The RadGanttView pulls its scale from this property
double PixelLength
{
get { ... }
set
{
// How do I get these values?
var oldOffset = ???;
var oldExtent - ???;
// Trigger the actual change in the view.
PropertyChanged("PixelLength", ...);
var newExtent = ???;
???.HorizontalOffset = GetNewOffset(...);
}
}
}
<UserControl ... d:DataContext="{d:DesignInstance my:FooViewModel}">
<telerik:RadGanttView x:Name="Gantt">
<!-- ... -->
</telerik:RadGanttView>
</UserControl>
Things I've looked into: 我调查过的事情:
DependencyProperty
wrappers in the FooView
code-behind that just access corresponding properties in the RadGanttView
. DependencyProperty
在包装FooView
刚刚访问相应的属性代码隐藏RadGanttView
。 This seems like it both is a horrible abuse of the system - ie it doesn't seem to make sense to have a dependency property not backed by a DependencyObject
. DependencyObject
支持的依赖项属性似乎没有任何意义。 And also that it plain wouldn't work - in WPF, the view seems to "push" data into the view model, and I'd still have no way to actually get the current values, since the values of the wrapper properties would never get updated. Command
s, maybe? Command
? I'm fairly new at WPF, I have no clue how those work at all, merely a vague impression that they might be a loosely coupled way for the view model to talk to the view. IScrollingInfo
, not the whole view, I could live with that. IScrollingInfo
,而不是整个视图,因此我可以接受。 Attached Behaviors may solve your issue. 附加行为可能会解决您的问题。 They are basically Attached Properties with a callback.
它们基本上是带有回调的附加属性。
Check out my answer here . 在这里查看我的答案。 Just instead of
KeyDown
event, you register to the Changed
event (or whatever your control is actually calling it) and then assign the value you get from the Changed event to your Attached Property, and you have two way binding on a non-bindable property 仅注册
Changed
事件(或控件实际调用的任何事件),而不是KeyDown
事件,然后将您从Changed事件获得的值分配给Attached Property,并且在非绑定属性上有两种绑定方式
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.