编译的绑定 (x:Bind) 是否需要 ViewModel 从 DependencyObject 派生?



我正在尝试在用Catel MVVM框架实现的项目上使用编译绑定(应该无关紧要(。但是,在生成的代码中,我收到编译器错误,因为我的ViewModel没有实现通常由DependencyObjects公开的某些函数:

CS1061 'MainViewModel' 不包含 'RegisterPropertyChangedCallback' 的定义,并且找不到接受类型为 'MainViewModel' 的第一个参数的扩展方法 'RegisterPropertyChangedCallback' (您是否缺少 using 指令或程序集引用?

也:

CS0039 无法通过引用转换、装箱转换、取消装箱转换、包装转换或空类型转换将类型"Windows.UI.Xaml.DependencyObject"转换为"CatelCompiledBindingTest.ViewModels.MainViewModel">

引发错误的x:Bind编译器生成的代码如下:

public void DependencyPropertyChanged_VM_Visible(global::Windows.UI.Xaml.DependencyObject sender, global::Windows.UI.Xaml.DependencyProperty prop)
{
MainView_obj1_Bindings bindings = TryGetBindingObject();
if (bindings != null)
{
global::CatelCompiledBindingTest.ViewModels.MainViewModel obj = sender as global::CatelCompiledBindingTest.ViewModels.MainViewModel;
if (obj != null)
{
bindings.Update_VM_Visible(obj.Visible, DATA_CHANGED);
}
}
}
private global::CatelCompiledBindingTest.ViewModels.MainViewModel cache_VM = null;
private long tokenDPC_VM_Visible = 0;
public void UpdateChildListeners_VM(global::CatelCompiledBindingTest.ViewModels.MainViewModel obj)
{
if (obj != cache_VM)
{
if (cache_VM != null)
{
((global::System.ComponentModel.INotifyPropertyChanged)cache_VM).PropertyChanged -= PropertyChanged_VM;
cache_VM.UnregisterPropertyChangedCallback(global::CatelCompiledBindingTest.ViewModels.MainViewModel.VisibleProperty, tokenDPC_VM_Visible);
cache_VM = null;
}
if (obj != null)
{
cache_VM = obj;
((global::System.ComponentModel.INotifyPropertyChanged)obj).PropertyChanged += PropertyChanged_VM;
tokenDPC_VM_Visible = obj.RegisterPropertyChangedCallback(global::CatelCompiledBindingTest.ViewModels.MainViewModel.VisibleProperty, DependencyPropertyChanged_VM_Visible);
}
}
}

MainViewModel相当简单(不包括Catel样板代码(:

public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
ToggleVisibility = new Command(OnToggleVisibilityExecute);
AddText = new Command(OnAddTextExecute);
SomeText = "";
}
//ViewModel properties
public string SomeText
{
get { return GetValue<string>(SometextProperty); }
set { SetValue(SometextProperty, value); }
}
public bool Visible
{
get { return GetValue<bool>(VisibleProperty); }
set { SetValue(VisibleProperty, value); }
}
//ViewModel Commands
public Command ToggleVisibility { get; private set; }
public void OnToggleVisibilityExecute()
{
Visible = !Visible;
}
public Command AddText { get; private set; }
public void OnAddTextExecute()
{
SomeText += "Random text! ";
}
}

视图如下:

<controls:Page
x:Class="CatelCompiledBindingTest.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CatelCompiledBindingTest.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Catel.Windows.Controls"
xmlns:converters="using:Catel.MVVM.Converters"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<converters:BooleanToCollapsingVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>
<Grid>
<Grid.KeyboardAccelerators>
<KeyboardAccelerator Invoked="{x:Bind VM.OnToggleVisibilityExecute}" Key="T" Modifiers="Control"/>
<KeyboardAccelerator Invoked="{x:Bind VM.OnAddTextExecute}" Key="Add" Modifiers="Control"/>
</Grid.KeyboardAccelerators>
<Border Width="500" Height="500" Visibility="{x:Bind VM.Visible, Mode=OneWay}" Background="SlateGray">
<TextBlock Style="{ThemeResource HeaderTextBlockStyle}" Text="{x:Bind VM.SomeText, Mode=OneWay}"/>
</Border>
</Grid>
</controls:Page>

使用以下代码隐藏,以便能够使用已编译的绑定:

public sealed partial class MainView : Page
{
public MainView()
{
this.InitializeComponent();
VM = DataContext as MainViewModel;
}
public MainViewModel VM { get; set; }
}

现在的问题是:为什么编译器在编译器生成的DependencyPropertyChanged_VM_Visible中假定 MainViewModel 属于DependencyObject类型?根据深度数据绑定,视图模型只需要实现它所做的IPropertyChanged

我该如何解决此问题(除了再次求助于{Binding}(?我需要在 ViewModel 中包含哪些命名空间才能使编译的绑定正常工作?

它假定它是一个依赖属性,因为VM属性是在视图MainView上声明的。应将VM属性定义为依赖项属性,以便可以绑定到(因此不是属性的值/类型,而是属性本身(。

最新更新