我在我的应用中使用了Caliburn.Micro。我想做的是:
到目前为止,我的ViewModel上有两个属性(我在这里省略INotify...Changed
及其实现,因为它可以工作):
BindableCollection<LicenceInfo> AvailableLicences { get; set; }
LicenceInfo ActiveLicence { get; set; }
在ViewModel的构造函数中,我填充AvailableLicences
和ActiveLicence
。到目前为止,非常好。
目前在视图中,我有一个ItemsControl
,其中包含RadioButton
和一个不可见的FrameworkElement
,可以传递给MyConverter
,我在其中提取{{1} {}}的DataContext
和不可见的Self
(其FrameworkElement
绑定到ViewModel)并将它们与(重写)DataContext
进行比较:
LicenceInfo.Equals()
这实际上是按预期工作的,但在我看来,这似乎是一个丑陋的解决方法,我确信我错过了一些东西。
使用<FrameworkElement Name="ActiveLicence" Visibility="Collapsed" />
<ItemsControl Name="AvailableLicences">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton cal:Message.Attach="[Event Checked] = [Action ChangeActiveLicence($dataContext)]">
<RadioButton.IsChecked>
<MultiBinding Converter="{StaticResource MyConverter}" Mode="OneWay">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding ElementName="ActiveLicence" />
</MultiBinding>
</RadioButton.IsChecked>
[...]
或<Binding x:Name="ActiveLicence" />
作为第二个参数并删除不可见的<Binding Path="ActiveLicence" />
不起作用,ViewModel属性未附加到绑定。
我不一定要使用FrameworkElement
。任何与处理MultiBinding
事件的动作类似的Caliburn.Micro动作都会受到欢迎。有什么想法吗?
答案 0 :(得分:1)
从我的角度来看,如果在LicenceViewModel上添加一个标志不是一个选项,那么你在这里非常接近一个好的解决方案:
尝试以下多重绑定,而不是使用容器框架元素:
<MultiBinding Converter="{StaticResource MyConverter}" Mode="OneWay">
<Binding Path="DataContext" RelativeSource="{RelativeSource Self}" />
<Binding Path="DataContext.ActiveLicense" RelativeSource="{RelativeSource FindAncestor, AncestorType=ItemsControl}" />
</MultiBinding>
修改转换器以使用Equals()
比较两个对象,与具体类型无关。这样,你就不会搞乱不必要的对象,仍然可以正确地分离 Views 和 ViewModels 。
修改强>
关于带有标志的替代解决方案:我没有注意到,您的代码中没有涉及LicenseViewModel ...在许可证信息中添加标志不是一个好的解决方案,我同意。您可以考虑将LicenseInfo
包装在LicenseInfoViewModel
内,但这需要一些基础结构来进行模型上LicenseInfo
的原始集合与包含该ViewModel
的集合之间的同步。 ViewModel
秒。
我已就该主题here发布了广泛的答案。
然后,当ActiveLicense
属性发生更改时,您可以将活动许可证{{1}}的标志设置为true,将所有其他标志设置为false。
这是一个具体背景的问题,在这里加倍努力是否有意义。如果您不打算随着时间的推移扩展功能等,而且只是简单的许可证选择,第一种解决方案就足够了。